This commit is contained in:
J. Duke 2017-07-05 17:47:31 +02:00
commit 1fba1e7db7
256 changed files with 26322 additions and 12878 deletions

View File

@ -117,3 +117,7 @@ d1cf7d4ee16c341f5b8c7e7f1d68a8c412b6c693 jdk7-b137
f4298bc3f4b6baa315643be06966f09684290068 jdk7-b140 f4298bc3f4b6baa315643be06966f09684290068 jdk7-b140
5d86d0c7692e8f4a58d430d68c03594e2d3403b3 jdk7-b141 5d86d0c7692e8f4a58d430d68c03594e2d3403b3 jdk7-b141
92bf0655022d4187e9b49c1400f98fb3392a4630 jdk7-b142 92bf0655022d4187e9b49c1400f98fb3392a4630 jdk7-b142
4a05062d8c4dfa3edec3faf1052af28baba5adff jdk7-b143
07a8728ad49ef6dfa469c3a8bf5ab1e9c80bed5c jdk7-b144
8294c99e685a1f6d1d37c45cd97854cf74be771e jdk7-b145
dca1e8a87e8f756f95b99bac8fe795750d42e1b0 jdk7-b146

View File

@ -117,3 +117,8 @@ fc47c97bbbd91b1f774d855c48a7e285eb1a351a jdk7-b138
dcfe74f1c6553c556e7d361c30b0b614eb5e40f6 jdk7-b140 dcfe74f1c6553c556e7d361c30b0b614eb5e40f6 jdk7-b140
c6569c5585851dfd39b8de8e021c3c312f51af12 jdk7-b141 c6569c5585851dfd39b8de8e021c3c312f51af12 jdk7-b141
cfbbdb77eac0397b03eb99ee2e07ea00e0a7b81e jdk7-b142 cfbbdb77eac0397b03eb99ee2e07ea00e0a7b81e jdk7-b142
14b8e7eee1058fd4ed5a2700a2ce14b3616278f1 jdk7-b143
7203965666a4fe63bf82f5e4204f41ce6285e716 jdk7-b144
55e9ebf032186c333e5964ed044419830ac02693 jdk7-b145
2d38c2a79c144c30cd04d143d83ee7ec6af40771 jdk7-b146
d91364304d7c4ecd34caffdba2b840aeb0d10b51 jdk7-b147

View File

@ -1 +1 @@
project=jdk7 project=jdk8

File diff suppressed because it is too large Load Diff

View File

@ -117,3 +117,7 @@ a66c01d8bf895261715955df0b95545c000ed6a8 jdk7-b137
cdf5d19ec142424489549025e9c42e51f32cf688 jdk7-b140 cdf5d19ec142424489549025e9c42e51f32cf688 jdk7-b140
a58635cdd921bafef353f4864184a0481353197b jdk7-b141 a58635cdd921bafef353f4864184a0481353197b jdk7-b141
a2f340a048c88d10cbedc0504f5cf03d39925a40 jdk7-b142 a2f340a048c88d10cbedc0504f5cf03d39925a40 jdk7-b142
51ed32f6f4de56f16e910ac54ba6c6f6606f4f17 jdk7-b143
7033a5756ad552d88114594d8e2d2e4dc2c05963 jdk7-b144
77ec0541aa2aa4da27e9e385a118a2e51e7fca24 jdk7-b145
770227a4087e4e401fe87ccd19738440111c3948 jdk7-b146

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2011, 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
@ -405,8 +405,7 @@ public class ObjectStreamClass implements java.io.Serializable {
if (!serializable || if (!serializable ||
externalizable || externalizable ||
forProxyClass || forProxyClass ||
name.equals("java.lang.String") || name.equals("java.lang.String")){
isEnum) {
fields = NO_FIELDS; fields = NO_FIELDS;
} else if (serializable) { } else if (serializable) {
/* Ask for permission to override field access checks. /* Ask for permission to override field access checks.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2010 Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2010, 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

View File

@ -117,3 +117,7 @@ be3758943770a0a3dd4be6a1cb4063507c4d7062 jdk7-b138
c8136fd161c83917f87e93b14fa2ba3483f9be83 jdk7-b140 c8136fd161c83917f87e93b14fa2ba3483f9be83 jdk7-b140
e1b5ef243445bf836d095fd44866e1771ef99374 jdk7-b141 e1b5ef243445bf836d095fd44866e1771ef99374 jdk7-b141
7d067af4b25e4b7e6b28bef48527d67f8650e6c5 jdk7-b142 7d067af4b25e4b7e6b28bef48527d67f8650e6c5 jdk7-b142
16b847e9bbd747f9d27785b2fc20d4d720cca893 jdk7-b143
39bf6dcaab2336326b21743cef7042d0a2de9ba0 jdk7-b144
10ca7570f47f2ae4132648f7e8da1a05f1a98a15 jdk7-b145
bcd31fa1e3c6f51b4fdd427ef905188cdac57164 jdk7-b146

File diff suppressed because it is too large Load Diff

View File

@ -25,8 +25,8 @@
drops.master.copy.base=${drops.dir} drops.master.copy.base=${drops.dir}
jaxp_src.bundle.name=jaxp-1_4_5.zip jaxp_src.bundle.name=jaxp145_01.zip
jaxp_src.bundle.md5.checksum=485e731f26f35d4efe05a63c57104374 jaxp_src.bundle.md5.checksum=32394c780c8fb5e29775f623525993c0
jaxp_src.master.bundle.dir=${drops.master.copy.base} jaxp_src.master.bundle.dir=${drops.master.copy.base}
jaxp_src.master.bundle.url.base=http://download.java.net/jaxp/1.4.5 jaxp_src.master.bundle.url.base=http://download.java.net/jaxp/1.4.5

View File

@ -117,3 +117,7 @@ c025078c8362076503bb83b8e4da14ba7b347940 jdk7-b139
82a9022c4f21b1313023c8303b557a17c4106701 jdk7-b140 82a9022c4f21b1313023c8303b557a17c4106701 jdk7-b140
66826b0aec5a1834da3821c35cf85ac154e9b04d jdk7-b141 66826b0aec5a1834da3821c35cf85ac154e9b04d jdk7-b141
0ef3ef823c39eee3d670e58027c3219cb66f0283 jdk7-b142 0ef3ef823c39eee3d670e58027c3219cb66f0283 jdk7-b142
569d1e7ea980d172046c4aba79d96b5c3afabbba jdk7-b143
6bd683f2d527c9afd47beac1cbf614506929598d jdk7-b144
42bfba80beb7d3260b7b135b9a39202b512eb8c2 jdk7-b145
05469dd4c3662c454f8a019e492543add60795cc jdk7-b146

File diff suppressed because it is too large Load Diff

View File

@ -25,8 +25,8 @@
drops.master.copy.base=${drops.dir} drops.master.copy.base=${drops.dir}
jaxws_src.bundle.name=jdk7-jaxws2_2_4-b02-2011_05_09.zip jaxws_src.bundle.name=jdk7-jaxws2_2_4-b03-2011_05_27.zip
jaxws_src.bundle.md5.checksum=0972a58090e8b2735d91a2f5d1ae1964 jaxws_src.bundle.md5.checksum=2f5b829ade70f67fe272d0b322e3e702
jaxws_src.master.bundle.dir=${drops.master.copy.base} jaxws_src.master.bundle.dir=${drops.master.copy.base}
jaxws_src.master.bundle.url.base=http://download.java.net/glassfish/components/jax-ws/openjdk/jdk7 jaxws_src.master.bundle.url.base=http://download.java.net/glassfish/components/jax-ws/openjdk/jdk7

View File

@ -117,3 +117,7 @@ d80954a89b49fda47c0c5cace65a17f5a758b8bd jdk7-b139
9315c733fb17ddfb9fb44be7e0ffea37bf3c727d jdk7-b140 9315c733fb17ddfb9fb44be7e0ffea37bf3c727d jdk7-b140
63eeefe118da18c75ba3d36266768cd1ccaaca6b jdk7-b141 63eeefe118da18c75ba3d36266768cd1ccaaca6b jdk7-b141
312612e89ece62633f4809706dec00bcd5fe7c2d jdk7-b142 312612e89ece62633f4809706dec00bcd5fe7c2d jdk7-b142
efbf75c24b0f31847c9c403f6dc07dc80551908d jdk7-b143
23bdcede4e3945894574892e80b848bd9f15b5f3 jdk7-b144
1e04b38b3824a4a1d197ef681a302e6813e53f8b jdk7-b145
539e576793a8e64aaf160e0d6ab0b9723cd0bef0 jdk7-b146

File diff suppressed because it is too large Load Diff

View File

@ -48,6 +48,9 @@ include Exportedfiles.gmk
ifeq ($(PLATFORM), solaris) ifeq ($(PLATFORM), solaris)
OTHER_LDLIBS += -ldoor OTHER_LDLIBS += -ldoor
endif endif
ifeq ($(PLATFORM), windows)
EXTRA_LIBS += psapi.lib
endif
vpath %.c $(PLATFORM_SRC)/native/sun/tools/attach vpath %.c $(PLATFORM_SRC)/native/sun/tools/attach

View File

@ -49,5 +49,16 @@ RUNTIME_NAME = $(PRODUCT_NAME) $(PRODUCT_SUFFIX)
JRE_REDUCED_HEADLESS_IMAGE_DIR = $(ABS_OUTPUTDIR)/j2re-reduced-headless-image JRE_REDUCED_HEADLESS_IMAGE_DIR = $(ABS_OUTPUTDIR)/j2re-reduced-headless-image
JRE_REDUCED_IMAGE_DIR = $(ABS_OUTPUTDIR)/j2re-reduced-image JRE_REDUCED_IMAGE_DIR = $(ABS_OUTPUTDIR)/j2re-reduced-image
# Override on linux to further reduce binary/lib sizes in product build
ifeq ($(PLATFORM), linux)
ifeq ($(VARIANT), OPT)
ifneq ($(NO_STRIP), true)
ifneq ($(DEBUG_BINARIES), true)
POST_STRIP_PROCESS = $(STRIP) --strip-unneeded
endif
endif
endif
endif
endif # JAVASE_EMBEDDED endif # JAVASE_EMBEDDED

View File

@ -53,25 +53,30 @@ $(NOT_HEADLESS_RT_JAR_LIST): $(NOT_RT_JAR_LIST)
$(RM) $(HEADLESS_CLASSLIST) $(RM) $(HEADLESS_CLASSLIST)
$(RM) $(NOT_HEADLESS_RT_JAR_LIST) $(RM) $(NOT_HEADLESS_RT_JAR_LIST)
$(CP) $(NOT_RT_JAR_LIST) $(NOT_HEADLESS_RT_JAR_LIST) $(CP) $(NOT_RT_JAR_LIST) $(NOT_HEADLESS_RT_JAR_LIST)
# List all the packages to be excluded
$(ECHO) "sun/awt/motif/" >> $@ $(ECHO) "sun/awt/motif/" >> $@
$(ECHO) "sun/awt/X11/" >> $@ $(ECHO) "sun/awt/X11/" >> $@
$(ECHO) "sun/applet/" >> $@ $(ECHO) "sun/applet/" >> $@
$(ECHO) "sun/java2d/opengl/" >> $@ $(ECHO) "sun/java2d/opengl/" >> $@
$(ECHO) "com/sun/java/swing/plaf/" >> $@ $(ECHO) "com/sun/java/swing/plaf/" >> $@
$(ECHO) "sun/awt/motif/MFontConfiguration" >$(HEADLESS_CLASSLIST) # List all the individual classes to be included
$(ECHO) "sun/applet/AppContextCreator" >>$(HEADLESS_CLASSLIST) $(ECHO) "sun/awt/motif/MFontConfiguration.class" >$(HEADLESS_CLASSLIST)
$(ECHO) "sun/applet/AppletAudioClip" >>$(HEADLESS_CLASSLIST) $(ECHO) "sun/applet/AppContextCreator.class" >>$(HEADLESS_CLASSLIST)
$(ECHO) "sun/java2d/opengl/GLXSurfaceData" >>$(HEADLESS_CLASSLIST) $(ECHO) "sun/applet/AppletAudioClip.class" >>$(HEADLESS_CLASSLIST)
$(ECHO) "sun/java2d/opengl/GLXSurfaceData"\$$"GLXOffScreenSurfaceData" >>$(HEADLESS_CLASSLIST) $(ECHO) "sun/java2d/opengl/GLXSurfaceData.class" >>$(HEADLESS_CLASSLIST)
$(ECHO) "sun/java2d/opengl/GLXVolatileSurfaceManager" >>$(HEADLESS_CLASSLIST) $(ECHO) "sun/java2d/opengl/GLXSurfaceData"\$$"GLXOffScreenSurfaceData.class" >>$(HEADLESS_CLASSLIST)
$(ECHO) "sun/java2d/opengl/OGLSurfaceData" >>$(HEADLESS_CLASSLIST) $(ECHO) "sun/java2d/opengl/GLXVolatileSurfaceManager.class" >>$(HEADLESS_CLASSLIST)
$(ECHO) "sun/java2d/opengl/OGLSurfaceData.class" >>$(HEADLESS_CLASSLIST)
$(TOTAL_HEADLESS_JAR_FILELIST): $(JARREORDER_JARFILE) $(NOT_HEADLESS_RT_JAR_LIST) $(TOTAL_HEADLESS_JAR_FILELIST): $(JARREORDER_JARFILE) $(NOT_HEADLESS_RT_JAR_LIST)
$(prep-target) $(prep-target)
$(RM) $@.temp $(RM) $@.temp
$(CD) $(CLASSBINDIR) ; \ $(CD) $(CLASSBINDIR) ; \
$(BOOT_JAVA_CMD) -jar $(JARREORDER_JARFILE) \ $(BOOT_JAVA_CMD) -jar $(JARREORDER_JARFILE) \
-o $@.temp $(HEADLESS_CLASSLIST) $(NOT_HEADLESS_RT_JAR_LIST) . -o $@.temp - $(NOT_HEADLESS_RT_JAR_LIST) .
# Add on the explicitly included class files from the otherwise excluded packages
$(CAT) $(HEADLESS_CLASSLIST) >> $@.temp
$(MV) $@.temp $@ $(MV) $@.temp $@
@$(CD) $(CLASSBINDIR); $(java-vm-cleanup) @$(CD) $(CLASSBINDIR); $(java-vm-cleanup)
@ -124,13 +129,9 @@ NOT_REDUCEDJRE_LIB = \
$(LIBARCH)/libjavaplugin_nscp.so \ $(LIBARCH)/libjavaplugin_nscp.so \
$(LIBARCH)/libjavaplugin_oji.so $(LIBARCH)/libjavaplugin_oji.so
# JRE docs that don't get included in reduced jre image top directory
ifeq ($(PLATFORM), linux) NOT_REDUCEDJRE_DOC = \
STRIP_OPTS = --strip-unneeded Welcome.html
else
STRIP_OPTS = -x
endif
reduced-image-jre:: reduced-image-jre::
@$(ECHO) Starting to Produce Reduced JRE @$(ECHO) Starting to Produce Reduced JRE
@ -142,12 +143,6 @@ reduced-image-jre::
$(CD) $(JRE_IMAGE_DIR); \ $(CD) $(JRE_IMAGE_DIR); \
$(TAR) cf - . | ($(CD) $(JRE_REDUCED_IMAGE_DIR); $(TAR) xf - ); $(TAR) cf - . | ($(CD) $(JRE_REDUCED_IMAGE_DIR); $(TAR) xf - );
@# strip the main .so files
$(STRIP) $(STRIP_OPTS) $(JRE_REDUCED_IMAGE_DIR)/lib/$(LIBARCH)/client/libjvm.so
ifndef BUILD_CLIENT_ONLY
$(STRIP) $(STRIP_OPTS) $(JRE_REDUCED_IMAGE_DIR)/lib/$(LIBARCH)/server/libjvm.so
endif
@# @#
@# Remove all of the files that are not needed for the @# Remove all of the files that are not needed for the
@# reduced JRE @# reduced JRE
@ -158,6 +153,9 @@ endif
for l in $(NOT_REDUCEDJRE_LIB) ; do \ for l in $(NOT_REDUCEDJRE_LIB) ; do \
$(RM) $(JRE_REDUCED_IMAGE_DIR)/lib/$$l ; \ $(RM) $(JRE_REDUCED_IMAGE_DIR)/lib/$$l ; \
done done
for l in $(NOT_REDUCEDJRE_DOC) ; do \
$(RM) $(JRE_REDUCED_IMAGE_DIR)/$$l ; \
done
@# Remove misc. other files @# Remove misc. other files
$(RM) -r $(JRE_REDUCED_IMAGE_DIR)/man $(RM) -r $(JRE_REDUCED_IMAGE_DIR)/man

View File

@ -900,8 +900,10 @@ initial-image-jdk-db: $(DB_ZIP_LIST)
for d in $(DB_ZIP_LIST); do \ for d in $(DB_ZIP_LIST); do \
($(CD) $(JDK_IMAGE_DIR)/db && $(UNZIP) -o $$d); \ ($(CD) $(JDK_IMAGE_DIR)/db && $(UNZIP) -o $$d); \
done done
$(CP) $(ABS_DB_PATH)/README-JDK.html $(JDK_IMAGE_DIR)/db
$(RM) -rf $(DEMODIR)/db $(RM) -rf $(DEMODIR)/db
$(MV) $(JDK_IMAGE_DIR)/db/demo $(DEMODIR)/db $(MV) $(JDK_IMAGE_DIR)/db/demo $(DEMODIR)/db
$(CP) $(ABS_DB_PATH)/README-JDK-DEMOS.html $(DEMODIR)/db/
$(RM) $(JDK_IMAGE_DIR)/db/index.html $(JDK_IMAGE_DIR)/db/register.html $(RM) $(JDK_IMAGE_DIR)/db/index.html $(JDK_IMAGE_DIR)/db/register.html
endif endif

View File

@ -370,8 +370,7 @@ $(SIGNED_POLICY_BUILDDIR)/limited/local_policy.jar: \
CLOSED_DIR = $(BUILDDIR)/closed/javax/crypto CLOSED_DIR = $(BUILDDIR)/closed/javax/crypto
release: $(SIGNED_DIR)/jce.jar sign-policy $(CLOSED_DIR)/doc/COPYRIGHT.html \ release: $(SIGNED_DIR)/jce.jar sign-policy $(CLOSED_DIR)/doc/README.txt
$(CLOSED_DIR)/doc/README.txt
$(RM) -r \ $(RM) -r \
$(JCE_BUILD_DIR)/release/UnlimitedJCEPolicy \ $(JCE_BUILD_DIR)/release/UnlimitedJCEPolicy \
$(JCE_BUILD_DIR)/release/jce.jar \ $(JCE_BUILD_DIR)/release/jce.jar \
@ -387,7 +386,6 @@ release: $(SIGNED_DIR)/jce.jar sign-policy $(CLOSED_DIR)/doc/COPYRIGHT.html \
$(CP) \ $(CP) \
$(SIGNED_POLICY_BUILDDIR)/unlimited/US_export_policy.jar \ $(SIGNED_POLICY_BUILDDIR)/unlimited/US_export_policy.jar \
$(SIGNED_POLICY_BUILDDIR)/unlimited/local_policy.jar \ $(SIGNED_POLICY_BUILDDIR)/unlimited/local_policy.jar \
$(CLOSED_DIR)/doc/COPYRIGHT.html \
$(CLOSED_DIR)/doc/README.txt \ $(CLOSED_DIR)/doc/README.txt \
$(JCE_BUILD_DIR)/release/UnlimitedJCEPolicy $(JCE_BUILD_DIR)/release/UnlimitedJCEPolicy
cd $(JCE_BUILD_DIR)/release ; \ cd $(JCE_BUILD_DIR)/release ; \

View File

@ -147,7 +147,7 @@ OTHER_INCLUDES += \
# Rules # Rules
# #
CLASSDESTDIR = $(TEMPDIR)/classes CLASSDESTDIR = $(TEMPDIR)/classes
JAVAHFLAGS += -classpath $(CLASSDESTDIR) JAVAHFLAGS += -Xbootclasspath/p:$(CLASSDESTDIR)
include $(BUILDDIR)/common/Mapfile-vers.gmk include $(BUILDDIR)/common/Mapfile-vers.gmk

View File

@ -1,4 +1,4 @@
." Copyright (c) 1998-2011 keytool tool, Oracle and/or its affiliates. All rights reserved. ." Copyright (c) 1998, 2011, 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

View File

@ -1,4 +1,4 @@
." Copyright (c) 1998-2011 keytool tool, Oracle and/or its affiliates. All rights reserved. ." Copyright (c) 1998, 2011, 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

View File

@ -174,8 +174,11 @@ class GTKFileChooserUI extends SynthFileChooserUI {
// construct the resulting string // construct the resulting string
for (int i=0; i<len; i++) { for (int i=0; i<len; i++) {
if (i > 0) {
buf.append(" ");
}
if (len > 1) { if (len > 1) {
buf.append(" \""); buf.append("\"");
} }
buf.append(result.get(i)); buf.append(result.get(i));
if (len > 1) { if (len > 1) {

View File

@ -56,9 +56,9 @@ FileChooser.deleteFileButtonMnemonic=76
FileChooser.renameFileButtonText=Rename File FileChooser.renameFileButtonText=Rename File
FileChooser.renameFileButtonMnemonic=82 FileChooser.renameFileButtonMnemonic=82
FileChooser.cancelButtonText=Cancel FileChooser.cancelButtonText=Cancel
#FileChooser.cancelButtonMnemonic=67 FileChooser.cancelButtonMnemonic=67
FileChooser.saveButtonText=OK FileChooser.saveButtonText=OK
#FileChooser.saveButtonMnemonic=79 FileChooser.saveButtonMnemonic=79
FileChooser.openButtonText=OK FileChooser.openButtonText=OK
FileChooser.openButtonMnemonic=79 FileChooser.openButtonMnemonic=79
FileChooser.saveDialogTitleText=Save FileChooser.saveDialogTitleText=Save
@ -79,5 +79,5 @@ FileChooser.renameFileDialogText=Rename file "{0}" to
FileChooser.renameFileErrorTitle=Error FileChooser.renameFileErrorTitle=Error
FileChooser.renameFileErrorText=Error renaming file "{0}" to "{1}" FileChooser.renameFileErrorText=Error renaming file "{0}" to "{1}"
#OptionPane.okButtonMnemonic=79 OptionPane.okButtonMnemonic=79
#OptionPane.cancelButtonMnemonic=67 OptionPane.cancelButtonMnemonic=67

View File

@ -1857,7 +1857,7 @@ public abstract class Toolkit {
/** /**
* Adds the specified property change listener for the named desktop * Adds the specified property change listener for the named desktop
* property. When a {@link PropertyChangeListenerProxy} object is added, * property. When a {@link java.beans.PropertyChangeListenerProxy} object is added,
* its property name is ignored, and the wrapped listener is added. * its property name is ignored, and the wrapped listener is added.
* If {@code name} is {@code null} or {@code pcl} is {@code null}, * If {@code name} is {@code null} or {@code pcl} is {@code null},
* no exception is thrown and no action is performed. * no exception is thrown and no action is performed.
@ -1874,7 +1874,7 @@ public abstract class Toolkit {
/** /**
* Removes the specified property change listener for the named * Removes the specified property change listener for the named
* desktop property. When a {@link PropertyChangeListenerProxy} object * desktop property. When a {@link java.beans.PropertyChangeListenerProxy} object
* is removed, its property name is ignored, and * is removed, its property name is ignored, and
* the wrapped listener is removed. * the wrapped listener is removed.
* If {@code name} is {@code null} or {@code pcl} is {@code null}, * If {@code name} is {@code null} or {@code pcl} is {@code null},
@ -1893,11 +1893,11 @@ public abstract class Toolkit {
/** /**
* Returns an array of all the property change listeners * Returns an array of all the property change listeners
* registered on this toolkit. The returned array * registered on this toolkit. The returned array
* contains {@code PropertyChangeListenerProxy} objects * contains {@link java.beans.PropertyChangeListenerProxy} objects
* that associate listeners with the names of desktop properties. * that associate listeners with the names of desktop properties.
* *
* @return all of this toolkit's {@ code PropertyChangeListener} * @return all of this toolkit's {@link PropertyChangeListener}
* objects wrapped in {@code PropertyChangeListenerProxy} objects * objects wrapped in {@code java.beans.PropertyChangeListenerProxy} objects
* or an empty array if no listeners are added * or an empty array if no listeners are added
* *
* @see PropertyChangeSupport#getPropertyChangeListeners() * @see PropertyChangeSupport#getPropertyChangeListeners()

View File

@ -1382,13 +1382,19 @@ public class ICC_Profile implements Serializable {
/** /**
* Sets a particular tagged data element in the profile from * Sets a particular tagged data element in the profile from
* a byte array. This method is useful * a byte array. The array should contain data in a format, corresponded
* for advanced applets or applications which need to access * to the {@code tagSignature} as defined in the ICC specification, section 10.
* profile data directly. * This method is useful for advanced applets or applications which need to
* access profile data directly.
* *
* @param tagSignature The ICC tag signature for the data element * @param tagSignature The ICC tag signature for the data element
* you want to set. * you want to set.
* @param tagData the data to set for the specified tag signature * @param tagData the data to set for the specified tag signature
* @throws IllegalArgumentException if {@code tagSignature} is not a signature
* as defined in the ICC specification.
* @throws IllegalArgumentException if a content of the {@code tagData}
* array can not be interpreted as valid tag data, corresponding
* to the {@code tagSignature}.
* @see #getData * @see #getData
*/ */
public void setData(int tagSignature, byte[] tagData) { public void setData(int tagSignature, byte[] tagData) {

View File

@ -1,7 +1,5 @@
/* /*
* %W% %E% * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
*
* Copyright (c) 2006, 2010 Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/ */

View File

@ -39,14 +39,14 @@ public class BootstrapMethodError extends LinkageError {
private static final long serialVersionUID = 292L; private static final long serialVersionUID = 292L;
/** /**
* Constructs an {@code BootstrapMethodError} with no detail message. * Constructs a {@code BootstrapMethodError} with no detail message.
*/ */
public BootstrapMethodError() { public BootstrapMethodError() {
super(); super();
} }
/** /**
* Constructs an {@code BootstrapMethodError} with the specified * Constructs a {@code BootstrapMethodError} with the specified
* detail message. * detail message.
* *
* @param s the detail message. * @param s the detail message.

View File

@ -38,6 +38,13 @@ import java.util.concurrent.atomic.AtomicInteger;
* @since 1.7 * @since 1.7
*/ */
public abstract class ClassValue<T> { public abstract class ClassValue<T> {
/**
* Sole constructor. (For invocation by subclass constructors, typically
* implicit.)
*/
protected ClassValue() {
}
/** /**
* Computes the given class's derived value for this {@code ClassValue}. * Computes the given class's derived value for this {@code ClassValue}.
* <p> * <p>
@ -100,7 +107,7 @@ public abstract class ClassValue<T> {
* If this value is subsequently {@linkplain #get read} for the same class, * If this value is subsequently {@linkplain #get read} for the same class,
* its value will be reinitialized by invoking its {@link #computeValue computeValue} method. * its value will be reinitialized by invoking its {@link #computeValue computeValue} method.
* This may result in an additional invocation of the * This may result in an additional invocation of the
* {@code computeValue computeValue} method for the given class. * {@code computeValue} method for the given class.
* <p> * <p>
* In order to explain the interaction between {@code get} and {@code remove} calls, * In order to explain the interaction between {@code get} and {@code remove} calls,
* we must model the state transitions of a class value to take into account * we must model the state transitions of a class value to take into account
@ -193,6 +200,7 @@ public abstract class ClassValue<T> {
= new WeakHashMap<Class<?>, ClassValueMap>(); = new WeakHashMap<Class<?>, ClassValueMap>();
private static ClassValueMap getMap(Class<?> type) { private static ClassValueMap getMap(Class<?> type) {
type.getClass(); // test for null
return ROOT.get(type); return ROOT.get(type);
} }

View File

@ -29,6 +29,8 @@ import sun.invoke.util.VerifyType;
import sun.invoke.util.Wrapper; import sun.invoke.util.Wrapper;
import sun.invoke.util.ValueConversions; import sun.invoke.util.ValueConversions;
import java.util.Arrays; import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collections;
import static java.lang.invoke.MethodHandleNatives.Constants.*; import static java.lang.invoke.MethodHandleNatives.Constants.*;
import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandleStatics.*;
@ -62,7 +64,7 @@ class AdapterMethodHandle extends BoundMethodHandle {
// the target and change its type, instead of adding another layer. // the target and change its type, instead of adding another layer.
/** Can a JVM-level adapter directly implement the proposed /** Can a JVM-level adapter directly implement the proposed
* argument conversions, as if by MethodHandles.convertArguments? * argument conversions, as if by fixed-arity MethodHandle.asType?
*/ */
static boolean canPairwiseConvert(MethodType newType, MethodType oldType, int level) { static boolean canPairwiseConvert(MethodType newType, MethodType oldType, int level) {
// same number of args, of course // same number of args, of course
@ -92,7 +94,7 @@ class AdapterMethodHandle extends BoundMethodHandle {
} }
/** Can a JVM-level adapter directly implement the proposed /** Can a JVM-level adapter directly implement the proposed
* argument conversion, as if by MethodHandles.convertArguments? * argument conversion, as if by fixed-arity MethodHandle.asType?
*/ */
static boolean canConvertArgument(Class<?> src, Class<?> dst, int level) { static boolean canConvertArgument(Class<?> src, Class<?> dst, int level) {
// ? Retool this logic to use RETYPE_ONLY, CHECK_CAST, etc., as opcodes, // ? Retool this logic to use RETYPE_ONLY, CHECK_CAST, etc., as opcodes,
@ -141,7 +143,7 @@ class AdapterMethodHandle extends BoundMethodHandle {
while (lastConv >= 0) { while (lastConv >= 0) {
Class<?> src = newType.parameterType(lastConv); // source type Class<?> src = newType.parameterType(lastConv); // source type
Class<?> dst = oldType.parameterType(lastConv); // destination type Class<?> dst = oldType.parameterType(lastConv); // destination type
if (VerifyType.isNullConversion(src, dst)) { if (isTrivialConversion(src, dst, level)) {
--lastConv; --lastConv;
} else { } else {
break; break;
@ -150,7 +152,7 @@ class AdapterMethodHandle extends BoundMethodHandle {
Class<?> needReturn = newType.returnType(); Class<?> needReturn = newType.returnType();
Class<?> haveReturn = oldType.returnType(); Class<?> haveReturn = oldType.returnType();
boolean retConv = !VerifyType.isNullConversion(haveReturn, needReturn); boolean retConv = !isTrivialConversion(haveReturn, needReturn, level);
// Now build a chain of one or more adapters. // Now build a chain of one or more adapters.
MethodHandle adapter = target, adapter2; MethodHandle adapter = target, adapter2;
@ -158,7 +160,7 @@ class AdapterMethodHandle extends BoundMethodHandle {
for (int i = 0; i <= lastConv; i++) { for (int i = 0; i <= lastConv; i++) {
Class<?> src = newType.parameterType(i); // source type Class<?> src = newType.parameterType(i); // source type
Class<?> dst = midType.parameterType(i); // destination type Class<?> dst = midType.parameterType(i); // destination type
if (VerifyType.isNullConversion(src, dst)) { if (isTrivialConversion(src, dst, level)) {
// do nothing: difference is trivial // do nothing: difference is trivial
continue; continue;
} }
@ -219,6 +221,22 @@ class AdapterMethodHandle extends BoundMethodHandle {
return adapter; return adapter;
} }
private static boolean isTrivialConversion(Class<?> src, Class<?> dst, int level) {
if (src == dst || dst == void.class) return true;
if (!VerifyType.isNullConversion(src, dst)) return false;
if (level > 1) return true; // explicitCastArguments
boolean sp = src.isPrimitive();
boolean dp = dst.isPrimitive();
if (sp != dp) return false;
if (sp) {
// in addition to being a null conversion, forbid boolean->int etc.
return Wrapper.forPrimitiveType(dst)
.isConvertibleFrom(Wrapper.forPrimitiveType(src));
} else {
return dst.isAssignableFrom(src);
}
}
private static MethodHandle makeReturnConversion(MethodHandle target, Class<?> haveReturn, Class<?> needReturn) { private static MethodHandle makeReturnConversion(MethodHandle target, Class<?> haveReturn, Class<?> needReturn) {
MethodHandle adjustReturn; MethodHandle adjustReturn;
if (haveReturn == void.class) { if (haveReturn == void.class) {
@ -387,13 +405,13 @@ class AdapterMethodHandle extends BoundMethodHandle {
insertStackMove(stackMove) insertStackMove(stackMove)
); );
} }
private static long makeSwapConv(int convOp, int srcArg, byte type, int destSlot) { private static long makeSwapConv(int convOp, int srcArg, byte srcType, int destSlot, byte destType) {
// more complex argument motion, requiring two slots to specify // more complex argument motion, requiring two slots to specify
assert(convOp == OP_SWAP_ARGS || convOp == OP_ROT_ARGS); assert(convOp == OP_SWAP_ARGS || convOp == OP_ROT_ARGS);
return ((long) srcArg << 32 | return ((long) srcArg << 32 |
(long) convOp << CONV_OP_SHIFT | (long) convOp << CONV_OP_SHIFT |
(int) type << CONV_SRC_TYPE_SHIFT | (int) srcType << CONV_SRC_TYPE_SHIFT |
(int) type << CONV_DEST_TYPE_SHIFT | (int) destType << CONV_DEST_TYPE_SHIFT |
(int) destSlot << CONV_VMINFO_SHIFT (int) destSlot << CONV_VMINFO_SHIFT
); );
} }
@ -530,6 +548,11 @@ class AdapterMethodHandle extends BoundMethodHandle {
} }
static MethodHandle makeVarargsCollector(MethodHandle target, Class<?> arrayType) { static MethodHandle makeVarargsCollector(MethodHandle target, Class<?> arrayType) {
MethodType type = target.type();
int last = type.parameterCount() - 1;
if (type.parameterType(last) != arrayType)
target = target.asType(type.changeParameterType(last, arrayType));
target = target.asFixedArity(); // make sure this attribute is turned off
return new AsVarargsCollector(target, arrayType); return new AsVarargsCollector(target, arrayType);
} }
@ -550,6 +573,11 @@ class AdapterMethodHandle extends BoundMethodHandle {
return true; return true;
} }
@Override
public MethodHandle asFixedArity() {
return target;
}
@Override @Override
public MethodHandle asType(MethodType newType) { public MethodHandle asType(MethodType newType) {
MethodType type = this.type(); MethodType type = this.type();
@ -574,14 +602,6 @@ class AdapterMethodHandle extends BoundMethodHandle {
cache = collector; cache = collector;
return collector.asType(newType); return collector.asType(newType);
} }
@Override
public MethodHandle asVarargsCollector(Class<?> arrayType) {
MethodType type = this.type();
if (type.parameterType(type.parameterCount()-1) == arrayType)
return this;
return super.asVarargsCollector(arrayType);
}
} }
/** Can a checkcast adapter validly convert the target to newType? /** Can a checkcast adapter validly convert the target to newType?
@ -596,7 +616,7 @@ class AdapterMethodHandle extends BoundMethodHandle {
|| !VerifyType.isNullConversion(castType, dst)) || !VerifyType.isNullConversion(castType, dst))
return false; return false;
int diff = diffTypes(newType, targetType, false); int diff = diffTypes(newType, targetType, false);
return (diff == arg+1); // arg is sole non-trivial diff return (diff == arg+1) || (diff == 0); // arg is sole non-trivial diff
} }
/** Can an primitive conversion adapter validly convert src to dst? */ /** Can an primitive conversion adapter validly convert src to dst? */
static boolean canCheckCast(Class<?> src, Class<?> dst) { static boolean canCheckCast(Class<?> src, Class<?> dst) {
@ -727,8 +747,31 @@ class AdapterMethodHandle extends BoundMethodHandle {
if (!canUnboxArgument(newType, oldType, arg, convType, level)) if (!canUnboxArgument(newType, oldType, arg, convType, level))
return null; return null;
MethodType castDone = newType; MethodType castDone = newType;
if (!VerifyType.isNullConversion(src, boxType)) if (!VerifyType.isNullConversion(src, boxType)) {
// Examples: Object->int, Number->int, Comparable->int; Byte->int, Character->int
if (level != 0) {
// must include additional conversions
if (src == Object.class || !Wrapper.isWrapperType(src)) {
// src must be examined at runtime, to detect Byte, Character, etc.
MethodHandle unboxMethod = (level == 1
? ValueConversions.unbox(dst)
: ValueConversions.unboxCast(dst));
long conv = makeConv(OP_COLLECT_ARGS, arg, basicType(src), basicType(dst));
return new AdapterMethodHandle(target, newType, conv, unboxMethod);
}
// Example: Byte->int
// Do this by reformulating the problem to Byte->byte.
Class<?> srcPrim = Wrapper.forWrapperType(src).primitiveType();
MethodType midType = newType.changeParameterType(arg, srcPrim);
MethodHandle fixPrim; // makePairwiseConvert(midType, target, 0);
if (canPrimCast(midType, oldType, arg, dst))
fixPrim = makePrimCast(midType, target, arg, dst);
else
fixPrim = target;
return makeUnboxArgument(newType, fixPrim, arg, srcPrim, 0);
}
castDone = newType.changeParameterType(arg, boxType); castDone = newType.changeParameterType(arg, boxType);
}
long conv = makeConv(OP_REF_TO_PRIM, arg, T_OBJECT, basicType(primType)); long conv = makeConv(OP_REF_TO_PRIM, arg, T_OBJECT, basicType(primType));
MethodHandle adapter = new AdapterMethodHandle(target, castDone, conv, boxType); MethodHandle adapter = new AdapterMethodHandle(target, castDone, conv, boxType);
if (castDone == newType) if (castDone == newType)
@ -897,13 +940,30 @@ class AdapterMethodHandle extends BoundMethodHandle {
if (swapArg1 == swapArg2) if (swapArg1 == swapArg2)
return target; return target;
if (swapArg1 > swapArg2) { int t = swapArg1; swapArg1 = swapArg2; swapArg2 = t; } if (swapArg1 > swapArg2) { int t = swapArg1; swapArg1 = swapArg2; swapArg2 = t; }
if (type2size(newType.parameterType(swapArg1)) !=
type2size(newType.parameterType(swapArg2))) {
// turn a swap into a pair of rotates:
// [x a b c y] rot2(-1,argc=5) => [a b c y x] rot1(+1,argc=4) => target[y a b c x]
int argc = swapArg2 - swapArg1 + 1;
final int ROT = 1;
ArrayList<Class<?>> rot1Params = new ArrayList<Class<?>>(target.type().parameterList());
Collections.rotate(rot1Params.subList(swapArg1, swapArg1 + argc), -ROT);
MethodType rot1Type = MethodType.methodType(target.type().returnType(), rot1Params);
MethodHandle rot1 = makeRotateArguments(rot1Type, target, swapArg1, argc, +ROT);
assert(rot1 != null);
if (argc == 2) return rot1;
MethodHandle rot2 = makeRotateArguments(newType, rot1, swapArg1, argc-1, -ROT);
assert(rot2 != null);
return rot2;
}
if (!canSwapArguments(newType, target.type(), swapArg1, swapArg2)) if (!canSwapArguments(newType, target.type(), swapArg1, swapArg2))
return null; return null;
Class<?> swapType = newType.parameterType(swapArg1); Class<?> type1 = newType.parameterType(swapArg1);
Class<?> type2 = newType.parameterType(swapArg2);
// in arglist: [0: ...keep1 | pos1: a1 | pos1+1: keep2... | pos2: a2 | pos2+1: keep3... ] // in arglist: [0: ...keep1 | pos1: a1 | pos1+1: keep2... | pos2: a2 | pos2+1: keep3... ]
// out arglist: [0: ...keep1 | pos1: a2 | pos1+1: keep2... | pos2: a1 | pos2+1: keep3... ] // out arglist: [0: ...keep1 | pos1: a2 | pos1+1: keep2... | pos2: a1 | pos2+1: keep3... ]
int swapSlot2 = newType.parameterSlotDepth(swapArg2 + 1); int swapSlot2 = newType.parameterSlotDepth(swapArg2 + 1);
long conv = makeSwapConv(OP_SWAP_ARGS, swapArg1, basicType(swapType), swapSlot2); long conv = makeSwapConv(OP_SWAP_ARGS, swapArg1, basicType(type1), swapSlot2, basicType(type2));
return new AdapterMethodHandle(target, newType, conv); return new AdapterMethodHandle(target, newType, conv);
} }
@ -926,7 +986,6 @@ class AdapterMethodHandle extends BoundMethodHandle {
static boolean canRotateArguments(MethodType newType, MethodType targetType, static boolean canRotateArguments(MethodType newType, MethodType targetType,
int firstArg, int argCount, int rotateBy) { int firstArg, int argCount, int rotateBy) {
if (!convOpSupported(OP_ROT_ARGS)) return false; if (!convOpSupported(OP_ROT_ARGS)) return false;
if (argCount <= 2) return false; // must be a swap, not a rotate
rotateBy = positiveRotation(argCount, rotateBy); rotateBy = positiveRotation(argCount, rotateBy);
if (rotateBy == 0) return false; // no rotation if (rotateBy == 0) return false; // no rotation
if (rotateBy > MAX_ARG_ROTATION && rotateBy < argCount - MAX_ARG_ROTATION) if (rotateBy > MAX_ARG_ROTATION && rotateBy < argCount - MAX_ARG_ROTATION)
@ -972,26 +1031,30 @@ class AdapterMethodHandle extends BoundMethodHandle {
// From here on out, it assumes a single-argument shift. // From here on out, it assumes a single-argument shift.
assert(MAX_ARG_ROTATION == 1); assert(MAX_ARG_ROTATION == 1);
int srcArg, dstArg; int srcArg, dstArg;
byte basicType; int dstSlot;
if (chunk2Slots <= chunk1Slots) { int moveChunk;
if (rotateBy == 1) {
// Rotate right/down N (rotateBy = +N, N small, c2 small): // Rotate right/down N (rotateBy = +N, N small, c2 small):
// in arglist: [0: ...keep1 | arg1: c1... | limit-N: c2 | limit: keep2... ] // in arglist: [0: ...keep1 | arg1: c1... | limit-N: c2 | limit: keep2... ]
// out arglist: [0: ...keep1 | arg1: c2 | arg1+N: c1... | limit: keep2... ] // out arglist: [0: ...keep1 | arg1: c2 | arg1+N: c1... | limit: keep2... ]
srcArg = limit-1; srcArg = limit-1;
dstArg = firstArg; dstArg = firstArg;
basicType = basicType(newType.parameterType(srcArg)); //dstSlot = depth0 - chunk2Slots; //chunk2Slots is not relevant
assert(chunk2Slots == type2size(basicType)); dstSlot = depth0 + MethodHandleNatives.OP_ROT_ARGS_DOWN_LIMIT_BIAS;
moveChunk = chunk2Slots;
} else { } else {
// Rotate left/up N (rotateBy = -N, N small, c1 small): // Rotate left/up N (rotateBy = -N, N small, c1 small):
// in arglist: [0: ...keep1 | arg1: c1 | arg1+N: c2... | limit: keep2... ] // in arglist: [0: ...keep1 | arg1: c1 | arg1+N: c2... | limit: keep2... ]
// out arglist: [0: ...keep1 | arg1: c2 ... | limit-N: c1 | limit: keep2... ] // out arglist: [0: ...keep1 | arg1: c2 ... | limit-N: c1 | limit: keep2... ]
srcArg = firstArg; srcArg = firstArg;
dstArg = limit-1; dstArg = limit-1;
basicType = basicType(newType.parameterType(srcArg)); dstSlot = depth2;
assert(chunk1Slots == type2size(basicType)); moveChunk = chunk1Slots;
} }
int dstSlot = newType.parameterSlotDepth(dstArg + 1); byte srcType = basicType(newType.parameterType(srcArg));
long conv = makeSwapConv(OP_ROT_ARGS, srcArg, basicType, dstSlot); byte dstType = basicType(newType.parameterType(dstArg));
assert(moveChunk == type2size(srcType));
long conv = makeSwapConv(OP_ROT_ARGS, srcArg, srcType, dstSlot, dstType);
return new AdapterMethodHandle(target, newType, conv); return new AdapterMethodHandle(target, newType, conv);
} }
@ -1033,8 +1096,9 @@ class AdapterMethodHandle extends BoundMethodHandle {
Class<?> spreadArgType, int spreadArgPos, int spreadArgCount) { Class<?> spreadArgType, int spreadArgPos, int spreadArgCount) {
// FIXME: Get rid of newType; derive new arguments from structure of spreadArgType // FIXME: Get rid of newType; derive new arguments from structure of spreadArgType
MethodType targetType = target.type(); MethodType targetType = target.type();
if (!canSpreadArguments(newType, targetType, spreadArgType, spreadArgPos, spreadArgCount)) assert(canSpreadArguments(newType, targetType, spreadArgType, spreadArgPos, spreadArgCount))
return null; : "[newType, targetType, spreadArgType, spreadArgPos, spreadArgCount] = "
+ Arrays.asList(newType, targetType, spreadArgType, spreadArgPos, spreadArgCount);
// dest is not significant; remove? // dest is not significant; remove?
int dest = T_VOID; int dest = T_VOID;
for (int i = 0; i < spreadArgCount; i++) { for (int i = 0; i < spreadArgCount; i++) {
@ -1127,7 +1191,7 @@ class AdapterMethodHandle extends BoundMethodHandle {
} }
@Override @Override
public String toString() { String debugString() {
return getNameString(nonAdapter((MethodHandle)vmtarget), this); return getNameString(nonAdapter((MethodHandle)vmtarget), this);
} }

View File

@ -151,11 +151,11 @@ class BoundMethodHandle extends MethodHandle {
final static RuntimeException badBoundArgumentException(Object argument, MethodHandle mh, int argnum) { final static RuntimeException badBoundArgumentException(Object argument, MethodHandle mh, int argnum) {
String atype = (argument == null) ? "null" : argument.getClass().toString(); String atype = (argument == null) ? "null" : argument.getClass().toString();
return new WrongMethodTypeException("cannot bind "+atype+" argument to parameter #"+argnum+" of "+mh.type()); return new ClassCastException("cannot bind "+atype+" argument to parameter #"+argnum+" of "+mh.type());
} }
@Override @Override
public String toString() { String debugString() {
return addTypeString(baseName(), this); return addTypeString(baseName(), this);
} }

View File

@ -111,7 +111,7 @@ public class CallSite {
} }
/** /**
* Make a blank call site object, possibly equipped with an initial target method handle. * Make a call site object equipped with an initial target method handle.
* @param target the method handle which will be the initial target of the call site * @param target the method handle which will be the initial target of the call site
* @throws NullPointerException if the proposed target is null * @throws NullPointerException if the proposed target is null
*/ */
@ -121,6 +121,25 @@ public class CallSite {
this.target = target; this.target = target;
} }
/**
* Make a call site object equipped with an initial target method handle.
* @param targetType the desired type of the call site
* @param createTargetHook a hook which will bind the call site to the target method handle
* @throws WrongMethodTypeException if the hook cannot be invoked on the required arguments,
* or if the target returned by the hook is not of the given {@code targetType}
* @throws NullPointerException if the hook returns a null value
* @throws ClassCastException if the hook returns something other than a {@code MethodHandle}
* @throws Throwable anything else thrown by the the hook function
*/
/*package-private*/
CallSite(MethodType targetType, MethodHandle createTargetHook) throws Throwable {
this(targetType);
ConstantCallSite selfCCS = (ConstantCallSite) this;
MethodHandle boundTarget = (MethodHandle) createTargetHook.invokeWithArguments(selfCCS);
checkTargetChange(this.target, boundTarget);
this.target = boundTarget;
}
/** /**
* Returns the type of this call site's target. * Returns the type of this call site's target.
* Although targets may change, any call site's type is permanent, and can never change to an unequal type. * Although targets may change, any call site's type is permanent, and can never change to an unequal type.
@ -129,6 +148,7 @@ public class CallSite {
* @return the type of the current target, which is also the type of any future target * @return the type of the current target, which is also the type of any future target
*/ */
public MethodType type() { public MethodType type() {
// warning: do not call getTarget here, because CCS.getTarget can throw IllegalStateException
return target.type(); return target.type();
} }
@ -294,8 +314,8 @@ public class CallSite {
} else { } else {
throw new ClassCastException("bootstrap method failed to produce a CallSite"); throw new ClassCastException("bootstrap method failed to produce a CallSite");
} }
assert(site.getTarget() != null); if (!site.getTarget().type().equals(type))
assert(site.getTarget().type().equals(type)); throw new WrongMethodTypeException("wrong type: "+site.getTarget());
} catch (Throwable ex) { } catch (Throwable ex) {
BootstrapMethodError bex; BootstrapMethodError bex;
if (ex instanceof BootstrapMethodError) if (ex instanceof BootstrapMethodError)

View File

@ -32,6 +32,8 @@ package java.lang.invoke;
* @author John Rose, JSR 292 EG * @author John Rose, JSR 292 EG
*/ */
public class ConstantCallSite extends CallSite { public class ConstantCallSite extends CallSite {
private final boolean isFrozen;
/** /**
* Creates a call site with a permanent target. * Creates a call site with a permanent target.
* @param target the target to be permanently associated with this call site * @param target the target to be permanently associated with this call site
@ -39,6 +41,45 @@ public class ConstantCallSite extends CallSite {
*/ */
public ConstantCallSite(MethodHandle target) { public ConstantCallSite(MethodHandle target) {
super(target); super(target);
isFrozen = true;
}
/**
* Creates a call site with a permanent target, possibly bound to the call site itself.
* <p>
* During construction of the call site, the {@code createTargetHook} is invoked to
* produce the actual target, as if by a call of the form
* {@code (MethodHandle) createTargetHook.invoke(this)}.
* <p>
* Note that user code cannot perform such an action directly in a subclass constructor,
* since the target must be fixed before the {@code ConstantCallSite} constructor returns.
* <p>
* The hook is said to bind the call site to a target method handle,
* and a typical action would be {@code someTarget.bindTo(this)}.
* However, the hook is free to take any action whatever,
* including ignoring the call site and returning a constant target.
* <p>
* The result returned by the hook must be a method handle of exactly
* the same type as the call site.
* <p>
* While the hook is being called, the new {@code ConstantCallSite}
* object is in a partially constructed state.
* In this state,
* a call to {@code getTarget}, or any other attempt to use the target,
* will result in an {@code IllegalStateException}.
* It is legal at all times to obtain the call site's type using the {@code type} method.
*
* @param targetType the type of the method handle to be permanently associated with this call site
* @param createTargetHook a method handle to invoke (on the call site) to produce the call site's target
* @throws WrongMethodTypeException if the hook cannot be invoked on the required arguments,
* or if the target returned by the hook is not of the given {@code targetType}
* @throws NullPointerException if the hook returns a null value
* @throws ClassCastException if the hook returns something other than a {@code MethodHandle}
* @throws Throwable anything else thrown by the the hook function
*/
protected ConstantCallSite(MethodType targetType, MethodHandle createTargetHook) throws Throwable {
super(targetType, createTargetHook);
isFrozen = true;
} }
/** /**
@ -48,9 +89,10 @@ public class ConstantCallSite extends CallSite {
* to the constructor call which created this instance. * to the constructor call which created this instance.
* *
* @return the immutable linkage state of this call site, a constant method handle * @return the immutable linkage state of this call site, a constant method handle
* @throws UnsupportedOperationException because this kind of call site cannot change its target * @throws IllegalStateException if the {@code ConstantCallSite} constructor has not completed
*/ */
@Override public final MethodHandle getTarget() { @Override public final MethodHandle getTarget() {
if (!isFrozen) throw new IllegalStateException();
return target; return target;
} }
@ -61,7 +103,7 @@ public class ConstantCallSite extends CallSite {
* @throws UnsupportedOperationException because this kind of call site cannot change its target * @throws UnsupportedOperationException because this kind of call site cannot change its target
*/ */
@Override public final void setTarget(MethodHandle ignore) { @Override public final void setTarget(MethodHandle ignore) {
throw new UnsupportedOperationException("ConstantCallSite"); throw new UnsupportedOperationException();
} }
/** /**
@ -69,6 +111,7 @@ public class ConstantCallSite extends CallSite {
* Since that target will never change, this is a correct implementation * Since that target will never change, this is a correct implementation
* of {@link CallSite#dynamicInvoker CallSite.dynamicInvoker}. * of {@link CallSite#dynamicInvoker CallSite.dynamicInvoker}.
* @return the immutable linkage state of this call site, a constant method handle * @return the immutable linkage state of this call site, a constant method handle
* @throws IllegalStateException if the {@code ConstantCallSite} constructor has not completed
*/ */
@Override @Override
public final MethodHandle dynamicInvoker() { public final MethodHandle dynamicInvoker() {

View File

@ -234,7 +234,7 @@ class FilterGeneric {
protected final MethodHandle target; // ultimate target protected final MethodHandle target; // ultimate target
@Override @Override
public String toString() { String debugString() {
return addTypeString(target, this); return addTypeString(target, this);
} }

View File

@ -41,7 +41,7 @@ class FilterOneArgument extends BoundMethodHandle {
protected final MethodHandle target; // Object -> Object protected final MethodHandle target; // Object -> Object
@Override @Override
public String toString() { String debugString() {
return target.toString(); return target.toString();
} }

View File

@ -260,7 +260,7 @@ class FromGeneric {
protected final MethodHandle target; // (any**N) => R protected final MethodHandle target; // (any**N) => R
@Override @Override
public String toString() { String debugString() {
return addTypeString(target, this); return addTypeString(target, this);
} }

View File

@ -129,20 +129,17 @@ class InvokeGeneric {
if (needType == erasedCallerType.returnType()) if (needType == erasedCallerType.returnType())
return false; // no conversions possible, since must be primitive or Object return false; // no conversions possible, since must be primitive or Object
Class<?> haveType = target.type().returnType(); Class<?> haveType = target.type().returnType();
if (VerifyType.isNullConversion(haveType, needType)) if (VerifyType.isNullConversion(haveType, needType) && !needType.isInterface())
return false; return false;
return true; return true;
} }
private MethodHandle addReturnConversion(MethodHandle target, Class<?> type) { private MethodHandle addReturnConversion(MethodHandle finisher, Class<?> type) {
if (true) throw new RuntimeException("NYI");
// FIXME: This is slow because it creates a closure node on every call that requires a return cast. // FIXME: This is slow because it creates a closure node on every call that requires a return cast.
MethodType targetType = target.type(); MethodType finisherType = finisher.type();
MethodHandle caster = ValueConversions.identity(type); MethodHandle caster = ValueConversions.identity(type);
caster = caster.asType(MethodType.methodType(type, targetType.returnType())); caster = caster.asType(caster.type().changeParameterType(0, finisherType.returnType()));
// Drop irrelevant arguments, because we only care about the return value: finisher = MethodHandles.filterReturnValue(finisher, caster);
caster = MethodHandles.dropArguments(caster, 1, targetType.parameterList()); return finisher.asType(finisherType);
MethodHandle result = MethodHandles.foldArguments(caster, target);
return result.asType(target.type());
} }
public String toString() { public String toString() {

View File

@ -46,7 +46,10 @@ class Invokers {
// general invoker for the outgoing call // general invoker for the outgoing call
private /*lazy*/ MethodHandle generalInvoker; private /*lazy*/ MethodHandle generalInvoker;
// general invoker for the outgoing call; accepts a single Object[] // general invoker for the outgoing call, uses varargs
private /*lazy*/ MethodHandle varargsInvoker;
// general invoker for the outgoing call; accepts a trailing Object[]
private final /*lazy*/ MethodHandle[] spreadInvokers; private final /*lazy*/ MethodHandle[] spreadInvokers;
// invoker for an unbound callsite // invoker for an unbound callsite
@ -67,45 +70,56 @@ class Invokers {
/*non-public*/ MethodHandle exactInvoker() { /*non-public*/ MethodHandle exactInvoker() {
MethodHandle invoker = exactInvoker; MethodHandle invoker = exactInvoker;
if (invoker != null) return invoker; if (invoker != null) return invoker;
try { invoker = lookupInvoker("invokeExact");
invoker = IMPL_LOOKUP.findVirtual(MethodHandle.class, "invokeExact", targetType);
} catch (ReflectiveOperationException ex) {
throw new InternalError("JVM cannot find invoker for "+targetType);
}
assert(invokerType(targetType) == invoker.type());
exactInvoker = invoker; exactInvoker = invoker;
return invoker; return invoker;
} }
/*non-public*/ MethodHandle generalInvoker() { /*non-public*/ MethodHandle generalInvoker() {
MethodHandle invoker1 = exactInvoker();
MethodHandle invoker = generalInvoker; MethodHandle invoker = generalInvoker;
if (invoker != null) return invoker; if (invoker != null) return invoker;
MethodType generalType = targetType.generic(); invoker = lookupInvoker("invoke");
invoker = invoker1.asType(invokerType(generalType));
generalInvoker = invoker; generalInvoker = invoker;
return invoker; return invoker;
} }
private MethodHandle lookupInvoker(String name) {
MethodHandle invoker;
try {
invoker = IMPL_LOOKUP.findVirtual(MethodHandle.class, name, targetType);
} catch (ReflectiveOperationException ex) {
throw new InternalError("JVM cannot find invoker for "+targetType);
}
assert(invokerType(targetType) == invoker.type());
assert(!invoker.isVarargsCollector());
return invoker;
}
/*non-public*/ MethodHandle erasedInvoker() { /*non-public*/ MethodHandle erasedInvoker() {
MethodHandle invoker1 = exactInvoker(); MethodHandle xinvoker = exactInvoker();
MethodHandle invoker = erasedInvoker; MethodHandle invoker = erasedInvoker;
if (invoker != null) return invoker; if (invoker != null) return invoker;
MethodType erasedType = targetType.erase(); MethodType erasedType = targetType.erase();
if (erasedType == targetType.generic()) invoker = xinvoker.asType(invokerType(erasedType));
invoker = generalInvoker();
else
invoker = invoker1.asType(invokerType(erasedType));
erasedInvoker = invoker; erasedInvoker = invoker;
return invoker; return invoker;
} }
/*non-public*/ MethodHandle spreadInvoker(int objectArgCount) { /*non-public*/ MethodHandle spreadInvoker(int leadingArgCount) {
MethodHandle vaInvoker = spreadInvokers[objectArgCount]; MethodHandle vaInvoker = spreadInvokers[leadingArgCount];
if (vaInvoker != null) return vaInvoker; if (vaInvoker != null) return vaInvoker;
MethodHandle gInvoker = generalInvoker(); MethodHandle gInvoker = generalInvoker();
vaInvoker = gInvoker.asSpreader(Object[].class, targetType.parameterCount() - objectArgCount); int spreadArgCount = targetType.parameterCount() - leadingArgCount;
spreadInvokers[objectArgCount] = vaInvoker; vaInvoker = gInvoker.asSpreader(Object[].class, spreadArgCount);
spreadInvokers[leadingArgCount] = vaInvoker;
return vaInvoker;
}
/*non-public*/ MethodHandle varargsInvoker() {
MethodHandle vaInvoker = varargsInvoker;
if (vaInvoker != null) return vaInvoker;
vaInvoker = spreadInvoker(0).asType(invokerType(MethodType.genericMethodType(0, true)));
varargsInvoker = vaInvoker;
return vaInvoker; return vaInvoker;
} }

View File

@ -506,8 +506,18 @@ import static java.lang.invoke.MethodHandleStatics.*;
if (from != null) message += ", from " + from; if (from != null) message += ", from " + from;
return new IllegalAccessException(message); return new IllegalAccessException(message);
} }
public ReflectiveOperationException makeAccessException(String message) { private String message() {
message = message + ": "+ toString(); if (isResolved())
return "no access";
else if (isConstructor())
return "no such constructor";
else if (isMethod())
return "no such method";
else
return "no such field";
}
public ReflectiveOperationException makeAccessException() {
String message = message() + ": "+ toString();
if (isResolved()) if (isResolved())
return new IllegalAccessException(message); return new IllegalAccessException(message);
else if (isConstructor()) else if (isConstructor())
@ -641,7 +651,7 @@ import static java.lang.invoke.MethodHandleStatics.*;
MemberName result = resolveOrNull(m, searchSupers, lookupClass); MemberName result = resolveOrNull(m, searchSupers, lookupClass);
if (result != null) if (result != null)
return result; return result;
ReflectiveOperationException ex = m.makeAccessException("no access"); ReflectiveOperationException ex = m.makeAccessException();
if (ex instanceof IllegalAccessException) throw (IllegalAccessException) ex; if (ex instanceof IllegalAccessException) throw (IllegalAccessException) ex;
throw nsmClass.cast(ex); throw nsmClass.cast(ex);
} }

View File

@ -26,6 +26,7 @@
package java.lang.invoke; package java.lang.invoke;
import java.util.ArrayList;
import sun.invoke.util.ValueConversions; import sun.invoke.util.ValueConversions;
import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandleStatics.*;
@ -40,12 +41,12 @@ import static java.lang.invoke.MethodHandleStatics.*;
* and {@linkplain java.lang.invoke.MethodHandles#filterArguments substitution}. * and {@linkplain java.lang.invoke.MethodHandles#filterArguments substitution}.
* *
* <h3>Method handle contents</h3> * <h3>Method handle contents</h3>
* Method handles are dynamically and strongly typed according to type descriptor. * Method handles are dynamically and strongly typed according to their parameter and return types.
* They are not distinguished by the name or defining class of their underlying methods. * They are not distinguished by the name or the defining class of their underlying methods.
* A method handle must be invoked using type descriptor which matches * A method handle must be invoked using a symbolic type descriptor which matches
* the method handle's own {@linkplain #type method type}. * the method handle's own {@linkplain #type type descriptor}.
* <p> * <p>
* Every method handle reports its type via the {@link #type type} accessor. * Every method handle reports its type descriptor via the {@link #type type} accessor.
* This type descriptor is a {@link java.lang.invoke.MethodType MethodType} object, * This type descriptor is a {@link java.lang.invoke.MethodType MethodType} object,
* whose structure is a series of classes, one of which is * whose structure is a series of classes, one of which is
* the return type of the method (or {@code void.class} if none). * the return type of the method (or {@code void.class} if none).
@ -82,7 +83,7 @@ import static java.lang.invoke.MethodHandleStatics.*;
* From the viewpoint of source code, these methods can take any arguments * From the viewpoint of source code, these methods can take any arguments
* and their result can be cast to any return type. * and their result can be cast to any return type.
* Formally this is accomplished by giving the invoker methods * Formally this is accomplished by giving the invoker methods
* {@code Object} return types and variable-arity {@code Object} arguments, * {@code Object} return types and variable arity {@code Object} arguments,
* but they have an additional quality called <em>signature polymorphism</em> * but they have an additional quality called <em>signature polymorphism</em>
* which connects this freedom of invocation directly to the JVM execution stack. * which connects this freedom of invocation directly to the JVM execution stack.
* <p> * <p>
@ -92,17 +93,17 @@ import static java.lang.invoke.MethodHandleStatics.*;
* and may not perform method invocation conversions on the arguments. * and may not perform method invocation conversions on the arguments.
* Instead, it must push them on the stack according to their own unconverted types. * Instead, it must push them on the stack according to their own unconverted types.
* The method handle object itself is pushed on the stack before the arguments. * The method handle object itself is pushed on the stack before the arguments.
* The compiler then calls the method handle with a type descriptor which * The compiler then calls the method handle with a symbolic type descriptor which
* describes the argument and return types. * describes the argument and return types.
* <p> * <p>
* To issue a complete type descriptor, the compiler must also determine * To issue a complete symbolic type descriptor, the compiler must also determine
* the return type. This is based on a cast on the method invocation expression, * the return type. This is based on a cast on the method invocation expression,
* if there is one, or else {@code Object} if the invocation is an expression * if there is one, or else {@code Object} if the invocation is an expression
* or else {@code void} if the invocation is a statement. * or else {@code void} if the invocation is a statement.
* The cast may be to a primitive type (but not {@code void}). * The cast may be to a primitive type (but not {@code void}).
* <p> * <p>
* As a corner case, an uncasted {@code null} argument is given * As a corner case, an uncasted {@code null} argument is given
* a type descriptor of {@code java.lang.Void}. * a symbolic type descriptor of {@code java.lang.Void}.
* The ambiguity with the type {@code Void} is harmless, since there are no references of type * The ambiguity with the type {@code Void} is harmless, since there are no references of type
* {@code Void} except the null reference. * {@code Void} except the null reference.
* *
@ -111,16 +112,16 @@ import static java.lang.invoke.MethodHandleStatics.*;
* it is linked, by symbolically resolving the names in the instruction * it is linked, by symbolically resolving the names in the instruction
* and verifying that the method call is statically legal. * and verifying that the method call is statically legal.
* This is true of calls to {@code invokeExact} and {@code invoke}. * This is true of calls to {@code invokeExact} and {@code invoke}.
* In this case, the type descriptor emitted by the compiler is checked for * In this case, the symbolic type descriptor emitted by the compiler is checked for
* correct syntax and names it contains are resolved. * correct syntax and names it contains are resolved.
* Thus, an {@code invokevirtual} instruction which invokes * Thus, an {@code invokevirtual} instruction which invokes
* a method handle will always link, as long * a method handle will always link, as long
* as the type descriptor is syntactically well-formed * as the symbolic type descriptor is syntactically well-formed
* and the types exist. * and the types exist.
* <p> * <p>
* When the {@code invokevirtual} is executed after linking, * When the {@code invokevirtual} is executed after linking,
* the receiving method handle's type is first checked by the JVM * the receiving method handle's type is first checked by the JVM
* to ensure that it matches the descriptor. * to ensure that it matches the symbolic type descriptor.
* If the type match fails, it means that the method which the * If the type match fails, it means that the method which the
* caller is invoking is not present on the individual * caller is invoking is not present on the individual
* method handle being invoked. * method handle being invoked.
@ -137,7 +138,7 @@ import static java.lang.invoke.MethodHandleStatics.*;
* (or other behavior, as the case may be). * (or other behavior, as the case may be).
* <p> * <p>
* A call to plain {@code invoke} works the same as a call to * A call to plain {@code invoke} works the same as a call to
* {@code invokeExact}, if the type descriptor specified by the caller * {@code invokeExact}, if the symbolic type descriptor specified by the caller
* exactly matches the method handle's own type. * exactly matches the method handle's own type.
* If there is a type mismatch, {@code invoke} attempts * If there is a type mismatch, {@code invoke} attempts
* to adjust the type of the receiving method handle, * to adjust the type of the receiving method handle,
@ -164,9 +165,9 @@ import static java.lang.invoke.MethodHandleStatics.*;
* method type matching takes into account both types names and class loaders. * method type matching takes into account both types names and class loaders.
* Thus, even if a method handle {@code M} is created in one * Thus, even if a method handle {@code M} is created in one
* class loader {@code L1} and used in another {@code L2}, * class loader {@code L1} and used in another {@code L2},
* method handle calls are type-safe, because the caller's type * method handle calls are type-safe, because the caller's symbolic type
* descriptor, as resolved in {@code L2}, * descriptor, as resolved in {@code L2},
* is matched against the original callee method's type descriptor, * is matched against the original callee method's symbolic type descriptor,
* as resolved in {@code L1}. * as resolved in {@code L1}.
* The resolution in {@code L1} happens when {@code M} is created * The resolution in {@code L1} happens when {@code M} is created
* and its type is assigned, while the resolution in {@code L2} happens * and its type is assigned, while the resolution in {@code L2} happens
@ -242,24 +243,24 @@ mt = MethodType.methodType(String.class, char.class, char.class);
mh = lookup.findVirtual(String.class, "replace", mt); mh = lookup.findVirtual(String.class, "replace", mt);
s = (String) mh.invokeExact("daddy",'d','n'); s = (String) mh.invokeExact("daddy",'d','n');
// invokeExact(Ljava/lang/String;CC)Ljava/lang/String; // invokeExact(Ljava/lang/String;CC)Ljava/lang/String;
assert(s.equals("nanny")); assertEquals(s, "nanny");
// weakly typed invocation (using MHs.invoke) // weakly typed invocation (using MHs.invoke)
s = (String) mh.invokeWithArguments("sappy", 'p', 'v'); s = (String) mh.invokeWithArguments("sappy", 'p', 'v');
assert(s.equals("savvy")); assertEquals(s, "savvy");
// mt is (Object[])List // mt is (Object[])List
mt = MethodType.methodType(java.util.List.class, Object[].class); mt = MethodType.methodType(java.util.List.class, Object[].class);
mh = lookup.findStatic(java.util.Arrays.class, "asList", mt); mh = lookup.findStatic(java.util.Arrays.class, "asList", mt);
assert(mh.isVarargsCollector()); assert(mh.isVarargsCollector());
x = mh.invoke("one", "two"); x = mh.invoke("one", "two");
// invoke(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object; // invoke(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;
assert(x.equals(java.util.Arrays.asList("one","two"))); assertEquals(x, java.util.Arrays.asList("one","two"));
// mt is (Object,Object,Object)Object // mt is (Object,Object,Object)Object
mt = MethodType.genericMethodType(3); mt = MethodType.genericMethodType(3);
mh = mh.asType(mt); mh = mh.asType(mt);
x = mh.invokeExact((Object)1, (Object)2, (Object)3); x = mh.invokeExact((Object)1, (Object)2, (Object)3);
// invokeExact(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; // invokeExact(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
assert(x.equals(java.util.Arrays.asList(1,2,3))); assertEquals(x, java.util.Arrays.asList(1,2,3));
// mt is int() // mt is ()int
mt = MethodType.methodType(int.class); mt = MethodType.methodType(int.class);
mh = lookup.findVirtual(java.util.List.class, "size", mt); mh = lookup.findVirtual(java.util.List.class, "size", mt);
i = (int) mh.invokeExact(java.util.Arrays.asList(1,2,3)); i = (int) mh.invokeExact(java.util.Arrays.asList(1,2,3));
@ -272,7 +273,10 @@ mh.invokeExact(System.out, "Hello, world.");
* </pre></blockquote> * </pre></blockquote>
* Each of the above calls to {@code invokeExact} or plain {@code invoke} * Each of the above calls to {@code invokeExact} or plain {@code invoke}
* generates a single invokevirtual instruction with * generates a single invokevirtual instruction with
* the type descriptor indicated in the following comment. * the symbolic type descriptor indicated in the following comment.
* In these examples, the helper method {@code assertEquals} is assumed to
* be a method which calls {@link Objects.equals java.util.Objects#equals}
* on its arguments, and asserts that the result is true.
* *
* <h3>Exceptions</h3> * <h3>Exceptions</h3>
* The methods {@code invokeExact} and {@code invoke} are declared * The methods {@code invokeExact} and {@code invoke} are declared
@ -283,7 +287,7 @@ mh.invokeExact(System.out, "Hello, world.");
* there is no particular effect on bytecode shape from ascribing * there is no particular effect on bytecode shape from ascribing
* checked exceptions to method handle invocations. But in Java source * checked exceptions to method handle invocations. But in Java source
* code, methods which perform method handle calls must either explicitly * code, methods which perform method handle calls must either explicitly
* throw {@code java.lang.Throwable Throwable}, or else must catch all * throw {@code Throwable}, or else must catch all
* throwables locally, rethrowing only those which are legal in the context, * throwables locally, rethrowing only those which are legal in the context,
* and wrapping ones which are illegal. * and wrapping ones which are illegal.
* *
@ -291,77 +295,26 @@ mh.invokeExact(System.out, "Hello, world.");
* The unusual compilation and linkage behavior of * The unusual compilation and linkage behavior of
* {@code invokeExact} and plain {@code invoke} * {@code invokeExact} and plain {@code invoke}
* is referenced by the term <em>signature polymorphism</em>. * is referenced by the term <em>signature polymorphism</em>.
* A signature polymorphic method is one which can operate with * As defined in the Java Language Specification,
* a signature polymorphic method is one which can operate with
* any of a wide range of call signatures and return types. * any of a wide range of call signatures and return types.
* In order to make this work, both the Java compiler and the JVM must
* give special treatment to signature polymorphic methods.
* <p> * <p>
* In source code, a call to a signature polymorphic method will * In source code, a call to a signature polymorphic method will
* compile, regardless of the requested type descriptor. * compile, regardless of the requested symbolic type descriptor.
* As usual, the Java compiler emits an {@code invokevirtual} * As usual, the Java compiler emits an {@code invokevirtual}
* instruction with the given type descriptor against the named method. * instruction with the given symbolic type descriptor against the named method.
* The unusual part is that the type descriptor is derived from * The unusual part is that the symbolic type descriptor is derived from
* the actual argument and return types, not from the method declaration. * the actual argument and return types, not from the method declaration.
* <p> * <p>
* When the JVM processes bytecode containing signature polymorphic calls, * When the JVM processes bytecode containing signature polymorphic calls,
* it will successfully link any such call, regardless of its type descriptor. * it will successfully link any such call, regardless of its symbolic type descriptor.
* (In order to retain type safety, the JVM will guard such calls with suitable * (In order to retain type safety, the JVM will guard such calls with suitable
* dynamic type checks, as described elsewhere.) * dynamic type checks, as described elsewhere.)
* <p> * <p>
* Bytecode generators, including the compiler back end, are required to emit * Bytecode generators, including the compiler back end, are required to emit
* untransformed type descriptors for these methods. * untransformed symbolic type descriptors for these methods.
* Tools which determine symbolic linkage are required to accept such * Tools which determine symbolic linkage are required to accept such
* untransformed descriptors, without reporting linkage errors. * untransformed descriptors, without reporting linkage errors.
* <p>
* For the sake of tools (but not as a programming API), the signature polymorphic
* methods are marked with a private yet standard annotation,
* {@code @java.lang.invoke.MethodHandle.PolymorphicSignature}.
* The annotation's retention is {@code RUNTIME}, so that all tools can see it.
*
* <h3>Formal rules for processing signature polymorphic methods</h3>
* <p>
* The following methods (and no others) are signature polymorphic:
* <ul>
* <li>{@link java.lang.invoke.MethodHandle#invokeExact MethodHandle.invokeExact}
* <li>{@link java.lang.invoke.MethodHandle#invoke MethodHandle.invoke}
* </ul>
* <p>
* A signature polymorphic method will be declared with the following properties:
* <ul>
* <li>It must be native.
* <li>It must take a single varargs parameter of the form {@code Object...}.
* <li>It must produce a return value of type {@code Object}.
* <li>It must be contained within the {@code java.lang.invoke} package.
* </ul>
* Because of these requirements, a signature polymorphic method is able to accept
* any number and type of actual arguments, and can, with a cast, produce a value of any type.
* However, the JVM will treat these declaration features as a documentation convention,
* rather than a description of the actual structure of the methods as executed.
* <p>
* When a call to a signature polymorphic method is compiled, the associated linkage information for
* its arguments is not array of {@code Object} (as for other similar varargs methods)
* but rather the erasure of the static types of all the arguments.
* <p>
* In an argument position of a method invocation on a signature polymorphic method,
* a null literal has type {@code java.lang.Void}, unless cast to a reference type.
* (<em>Note:</em> This typing rule allows the null type to have its own encoding in linkage information
* distinct from other types.
* <p>
* The linkage information for the return type is derived from a context-dependent target typing convention.
* The return type for a signature polymorphic method invocation is determined as follows:
* <ul>
* <li>If the method invocation expression is an expression statement, the method is {@code void}.
* <li>Otherwise, if the method invocation expression is the immediate operand of a cast,
* the return type is the erasure of the cast type.
* <li>Otherwise, the return type is the method's nominal return type, {@code Object}.
* </ul>
* (Programmers are encouraged to use explicit casts unless it is clear that a signature polymorphic
* call will be used as a plain {@code Object} expression.)
* <p>
* The linkage information for argument and return types is stored in the descriptor for the
* compiled (bytecode) call site. As for any invocation instruction, the arguments and return value
* will be passed directly on the JVM stack, in accordance with the descriptor,
* and without implicit boxing or unboxing.
* *
* <h3>Interoperation between method handles and the Core Reflection API</h3> * <h3>Interoperation between method handles and the Core Reflection API</h3>
* Using factory methods in the {@link java.lang.invoke.MethodHandles.Lookup Lookup} API, * Using factory methods in the {@link java.lang.invoke.MethodHandles.Lookup Lookup} API,
@ -385,14 +338,14 @@ mh.invokeExact(System.out, "Hello, world.");
* declared method, including in this case {@code native} and {@code varargs} bits. * declared method, including in this case {@code native} and {@code varargs} bits.
* <p> * <p>
* As with any reflected method, these methods (when reflected) may be * As with any reflected method, these methods (when reflected) may be
* invoked via {@link java.lang.reflect.Method#invoke Method.invoke}. * invoked via {@link java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}.
* However, such reflective calls do not result in method handle invocations. * However, such reflective calls do not result in method handle invocations.
* Such a call, if passed the required argument * Such a call, if passed the required argument
* (a single one, of type {@code Object[]}), will ignore the argument and * (a single one, of type {@code Object[]}), will ignore the argument and
* will throw an {@code UnsupportedOperationException}. * will throw an {@code UnsupportedOperationException}.
* <p> * <p>
* Since {@code invokevirtual} instructions can natively * Since {@code invokevirtual} instructions can natively
* invoke method handles under any type descriptor, this reflective view conflicts * invoke method handles under any symbolic type descriptor, this reflective view conflicts
* with the normal presentation of these methods via bytecodes. * with the normal presentation of these methods via bytecodes.
* Thus, these two native methods, when reflectively viewed by * Thus, these two native methods, when reflectively viewed by
* {@code Class.getDeclaredMethod}, may be regarded as placeholders only. * {@code Class.getDeclaredMethod}, may be regarded as placeholders only.
@ -413,7 +366,7 @@ mh.invokeExact(System.out, "Hello, world.");
* When a method handle is invoked, the types of its arguments * When a method handle is invoked, the types of its arguments
* or the return value cast type may be generic types or type instances. * or the return value cast type may be generic types or type instances.
* If this occurs, the compiler will replace those * If this occurs, the compiler will replace those
* types by their erasures when when it constructs the type descriptor * types by their erasures when it constructs the symbolic type descriptor
* for the {@code invokevirtual} instruction. * for the {@code invokevirtual} instruction.
* <p> * <p>
* Method handles do not represent * Method handles do not represent
@ -502,17 +455,17 @@ public abstract class MethodHandle {
/** /**
* Invokes the method handle, allowing any caller type descriptor, but requiring an exact type match. * Invokes the method handle, allowing any caller type descriptor, but requiring an exact type match.
* The type descriptor at the call site of {@code invokeExact} must * The symbolic type descriptor at the call site of {@code invokeExact} must
* exactly match this method handle's {@link #type type}. * exactly match this method handle's {@link #type type}.
* No conversions are allowed on arguments or return values. * No conversions are allowed on arguments or return values.
* <p> * <p>
* When this method is observed via the Core Reflection API, * When this method is observed via the Core Reflection API,
* it will appear as a single native method, taking an object array and returning an object. * it will appear as a single native method, taking an object array and returning an object.
* If this native method is invoked directly via * If this native method is invoked directly via
* {@link java.lang.reflect.Method#invoke Method.invoke}, via JNI, * {@link java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}, via JNI,
* or indirectly via {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect}, * or indirectly via {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect},
* it will throw an {@code UnsupportedOperationException}. * it will throw an {@code UnsupportedOperationException}.
* @throws WrongMethodTypeException if the target's type is not identical with the caller's type descriptor * @throws WrongMethodTypeException if the target's type is not identical with the caller's symbolic type descriptor
* @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call * @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call
*/ */
public final native @PolymorphicSignature Object invokeExact(Object... args) throws Throwable; public final native @PolymorphicSignature Object invokeExact(Object... args) throws Throwable;
@ -521,7 +474,7 @@ public abstract class MethodHandle {
* Invokes the method handle, allowing any caller type descriptor, * Invokes the method handle, allowing any caller type descriptor,
* and optionally performing conversions on arguments and return values. * and optionally performing conversions on arguments and return values.
* <p> * <p>
* If the call site type descriptor exactly matches this method handle's {@link #type type}, * If the call site's symbolic type descriptor exactly matches this method handle's {@link #type type},
* the call proceeds as if by {@link #invokeExact invokeExact}. * the call proceeds as if by {@link #invokeExact invokeExact}.
* <p> * <p>
* Otherwise, the call proceeds as if this method handle were first * Otherwise, the call proceeds as if this method handle were first
@ -534,7 +487,7 @@ public abstract class MethodHandle {
* adaptations directly on the caller's arguments, * adaptations directly on the caller's arguments,
* and call the target method handle according to its own exact type. * and call the target method handle according to its own exact type.
* <p> * <p>
* The type descriptor at the call site of {@code invoke} must * The resolved type descriptor at the call site of {@code invoke} must
* be a valid argument to the receivers {@code asType} method. * be a valid argument to the receivers {@code asType} method.
* In particular, the caller must specify the same argument arity * In particular, the caller must specify the same argument arity
* as the callee's type, * as the callee's type,
@ -543,24 +496,17 @@ public abstract class MethodHandle {
* When this method is observed via the Core Reflection API, * When this method is observed via the Core Reflection API,
* it will appear as a single native method, taking an object array and returning an object. * it will appear as a single native method, taking an object array and returning an object.
* If this native method is invoked directly via * If this native method is invoked directly via
* {@link java.lang.reflect.Method#invoke Method.invoke}, via JNI, * {@link java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}, via JNI,
* or indirectly via {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect}, * or indirectly via {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect},
* it will throw an {@code UnsupportedOperationException}. * it will throw an {@code UnsupportedOperationException}.
* @throws WrongMethodTypeException if the target's type cannot be adjusted to the caller's type descriptor * @throws WrongMethodTypeException if the target's type cannot be adjusted to the caller's symbolic type descriptor
* @throws ClassCastException if the target's type can be adjusted to the caller, but a reference cast fails * @throws ClassCastException if the target's type can be adjusted to the caller, but a reference cast fails
* @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call * @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call
*/ */
public final native @PolymorphicSignature Object invoke(Object... args) throws Throwable; public final native @PolymorphicSignature Object invoke(Object... args) throws Throwable;
/** /**
* <em>Temporary alias</em> for {@link #invoke}, for backward compatibility with some versions of JSR 292. * Performs a variable arity invocation, passing the arguments in the given array
* On some JVMs, support can be excluded by the flags {@code -XX:+UnlockExperimentalVMOptions -XX:-AllowInvokeGeneric}.
* @deprecated Will be removed for JSR 292 Proposed Final Draft.
*/
public final native @PolymorphicSignature Object invokeGeneric(Object... args) throws Throwable;
/**
* Performs a varargs invocation, passing the arguments in the given array
* to the method handle, as if via an inexact {@link #invoke invoke} from a call site * to the method handle, as if via an inexact {@link #invoke invoke} from a call site
* which mentions only the type {@code Object}, and whose arity is the length * which mentions only the type {@code Object}, and whose arity is the length
* of the argument array. * of the argument array.
@ -612,56 +558,16 @@ public abstract class MethodHandle {
public Object invokeWithArguments(Object... arguments) throws Throwable { public Object invokeWithArguments(Object... arguments) throws Throwable {
int argc = arguments == null ? 0 : arguments.length; int argc = arguments == null ? 0 : arguments.length;
MethodType type = type(); MethodType type = type();
if (type.parameterCount() != argc) { if (type.parameterCount() != argc || isVarargsCollector()) {
// simulate invoke // simulate invoke
return asType(MethodType.genericMethodType(argc)).invokeWithArguments(arguments); return asType(MethodType.genericMethodType(argc)).invokeWithArguments(arguments);
} }
if (argc <= 10) { MethodHandle invoker = type.invokers().varargsInvoker();
MethodHandle invoker = type.invokers().generalInvoker();
switch (argc) {
case 0: return invoker.invokeExact(this);
case 1: return invoker.invokeExact(this,
arguments[0]);
case 2: return invoker.invokeExact(this,
arguments[0], arguments[1]);
case 3: return invoker.invokeExact(this,
arguments[0], arguments[1], arguments[2]);
case 4: return invoker.invokeExact(this,
arguments[0], arguments[1], arguments[2],
arguments[3]);
case 5: return invoker.invokeExact(this,
arguments[0], arguments[1], arguments[2],
arguments[3], arguments[4]);
case 6: return invoker.invokeExact(this,
arguments[0], arguments[1], arguments[2],
arguments[3], arguments[4], arguments[5]);
case 7: return invoker.invokeExact(this,
arguments[0], arguments[1], arguments[2],
arguments[3], arguments[4], arguments[5],
arguments[6]);
case 8: return invoker.invokeExact(this,
arguments[0], arguments[1], arguments[2],
arguments[3], arguments[4], arguments[5],
arguments[6], arguments[7]);
case 9: return invoker.invokeExact(this,
arguments[0], arguments[1], arguments[2],
arguments[3], arguments[4], arguments[5],
arguments[6], arguments[7], arguments[8]);
case 10: return invoker.invokeExact(this,
arguments[0], arguments[1], arguments[2],
arguments[3], arguments[4], arguments[5],
arguments[6], arguments[7], arguments[8],
arguments[9]);
}
}
// more than ten arguments get boxed in a varargs list:
MethodHandle invoker = type.invokers().spreadInvoker(0);
return invoker.invokeExact(this, arguments); return invoker.invokeExact(this, arguments);
} }
/** /**
* Performs a varargs invocation, passing the arguments in the given array * Performs a variable arity invocation, passing the arguments in the given array
* to the method handle, as if via an inexact {@link #invoke invoke} from a call site * to the method handle, as if via an inexact {@link #invoke invoke} from a call site
* which mentions only the type {@code Object}, and whose arity is the length * which mentions only the type {@code Object}, and whose arity is the length
* of the argument array. * of the argument array.
@ -673,6 +579,7 @@ public abstract class MethodHandle {
* *
* @param arguments the arguments to pass to the target * @param arguments the arguments to pass to the target
* @return the result returned by the target * @return the result returned by the target
* @throws NullPointerException if {@code arguments} is a null reference
* @throws ClassCastException if an argument cannot be converted by reference casting * @throws ClassCastException if an argument cannot be converted by reference casting
* @throws WrongMethodTypeException if the target's type cannot be adjusted to take the given number of {@code Object} arguments * @throws WrongMethodTypeException if the target's type cannot be adjusted to take the given number of {@code Object} arguments
* @throws Throwable anything thrown by the target method invocation * @throws Throwable anything thrown by the target method invocation
@ -689,32 +596,105 @@ public abstract class MethodHandle {
* <p> * <p>
* If the original type and new type are equal, returns {@code this}. * If the original type and new type are equal, returns {@code this}.
* <p> * <p>
* The new method handle, when invoked, will perform the following
* steps:
* <ul>
* <li>Convert the incoming argument list to match the original
* method handle's argument list.
* <li>Invoke the original method handle on the converted argument list.
* <li>Convert any result returned by the original method handle
* to the return type of new method handle.
* </ul>
* <p>
* This method provides the crucial behavioral difference between * This method provides the crucial behavioral difference between
* {@link #invokeExact invokeExact} and plain, inexact {@link #invoke invoke}. The two methods * {@link #invokeExact invokeExact} and plain, inexact {@link #invoke invoke}.
* perform the same steps when the caller's type descriptor is identical * The two methods
* with the callee's, but when the types differ, plain {@link #invoke invoke} * perform the same steps when the caller's type descriptor exactly m atches
* the callee's, but when the types differ, plain {@link #invoke invoke}
* also calls {@code asType} (or some internal equivalent) in order * also calls {@code asType} (or some internal equivalent) in order
* to match up the caller's and callee's types. * to match up the caller's and callee's types.
* <p> * <p>
* This method is equivalent to {@link MethodHandles#convertArguments convertArguments}, * If the current method is a variable arity method handle
* except for variable arity method handles produced by {@link #asVarargsCollector asVarargsCollector}. * argument list conversion may involve the conversion and collection
* of several arguments into an array, as
* {@linkplain #asVarargsCollector described elsewhere}.
* In every other case, all conversions are applied <em>pairwise</em>,
* which means that each argument or return value is converted to
* exactly one argument or return value (or no return value).
* The applied conversions are defined by consulting the
* the corresponding component types of the old and new
* method handle types.
* <p>
* Let <em>T0</em> and <em>T1</em> be corresponding new and old parameter types,
* or old and new return types. Specifically, for some valid index {@code i}, let
* <em>T0</em>{@code =newType.parameterType(i)} and <em>T1</em>{@code =this.type().parameterType(i)}.
* Or else, going the other way for return values, let
* <em>T0</em>{@code =this.type().returnType()} and <em>T1</em>{@code =newType.returnType()}.
* If the types are the same, the new method handle makes no change
* to the corresponding argument or return value (if any).
* Otherwise, one of the following conversions is applied
* if possible:
* <ul>
* <li>If <em>T0</em> and <em>T1</em> are references, then a cast to <em>T1</em> is applied.
* (The types do not need to be related in any particular way.
* This is because a dynamic value of null can convert to any reference type.)
* <li>If <em>T0</em> and <em>T1</em> are primitives, then a Java method invocation
* conversion (JLS 5.3) is applied, if one exists.
* (Specifically, <em>T0</em> must convert to <em>T1</em> by a widening primitive conversion.)
* <li>If <em>T0</em> is a primitive and <em>T1</em> a reference,
* a Java casting conversion (JLS 5.5) is applied if one exists.
* (Specifically, the value is boxed from <em>T0</em> to its wrapper class,
* which is then widened as needed to <em>T1</em>.)
* <li>If <em>T0</em> is a reference and <em>T1</em> a primitive, an unboxing
* conversion will be applied at runtime, possibly followed
* by a Java method invocation conversion (JLS 5.3)
* on the primitive value. (These are the primitive widening conversions.)
* <em>T0</em> must be a wrapper class or a supertype of one.
* (In the case where <em>T0</em> is Object, these are the conversions
* allowed by {@link java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}.)
* The unboxing conversion must have a possibility of success, which means that
* if <em>T0</em> is not itself a wrapper class, there must exist at least one
* wrapper class <em>TW</em> which is a subtype of <em>T0</em> and whose unboxed
* primitive value can be widened to <em>T1</em>.
* <li>If the return type <em>T1</em> is marked as void, any returned value is discarded
* <li>If the return type <em>T0</em> is void and <em>T1</em> a reference, a null value is introduced.
* <li>If the return type <em>T0</em> is void and <em>T1</em> a primitive,
* a zero value is introduced.
* </ul>
* (<em>Note:</em> Both <em>T0</em> and <em>T1</em> may be regarded as static types,
* because neither corresponds specifically to the <em>dynamic type</em> of any
* actual argument or return value.)
* <p>
* The method handle conversion cannot be made if any one of the required
* pairwise conversions cannot be made.
* <p>
* At runtime, the conversions applied to reference arguments
* or return values may require additional runtime checks which can fail.
* An unboxing operation may fail because the original reference is null,
* causing a {@link java.lang.NullPointerException NullPointerException}.
* An unboxing operation or a reference cast may also fail on a reference
* to an object of the wrong type,
* causing a {@link java.lang.ClassCastException ClassCastException}.
* Although an unboxing operation may accept several kinds of wrappers,
* if none are available, a {@code ClassCastException} will be thrown.
* *
* @param newType the expected type of the new method handle * @param newType the expected type of the new method handle
* @return a method handle which delegates to {@code this} after performing * @return a method handle which delegates to {@code this} after performing
* any necessary argument conversions, and arranges for any * any necessary argument conversions, and arranges for any
* necessary return value conversions * necessary return value conversions
* @throws NullPointerException if {@code newType} is a null reference
* @throws WrongMethodTypeException if the conversion cannot be made * @throws WrongMethodTypeException if the conversion cannot be made
* @see MethodHandles#convertArguments * @see MethodHandles#explicitCastArguments
*/ */
public MethodHandle asType(MethodType newType) { public MethodHandle asType(MethodType newType) {
if (!type.isConvertibleTo(newType)) { if (!type.isConvertibleTo(newType)) {
throw new WrongMethodTypeException("cannot convert "+type+" to "+newType); throw new WrongMethodTypeException("cannot convert "+this+" to "+newType);
} }
return MethodHandles.convertArguments(this, newType); return MethodHandleImpl.convertArguments(this, newType, 1);
} }
/** /**
* Makes an adapter which accepts a trailing array argument * Makes an <em>array-spreading</em> method handle, which accepts a trailing array argument
* and spreads its elements as positional arguments. * and spreads its elements as positional arguments.
* The new method handle adapts, as its <i>target</i>, * The new method handle adapts, as its <i>target</i>,
* the current method handle. The type of the adapter will be * the current method handle. The type of the adapter will be
@ -739,26 +719,103 @@ public abstract class MethodHandle {
* contains exactly enough elements to provide a correct argument count * contains exactly enough elements to provide a correct argument count
* to the target method handle. * to the target method handle.
* (The array may also be null when zero elements are required.) * (The array may also be null when zero elements are required.)
* <p>
* Here are some simple examples of array-spreading method handles:
* <blockquote><pre>
MethodHandle equals = publicLookup()
.findVirtual(String.class, "equals", methodType(boolean.class, Object.class));
assert( (boolean) equals.invokeExact("me", (Object)"me"));
assert(!(boolean) equals.invokeExact("me", (Object)"thee"));
// spread both arguments from a 2-array:
MethodHandle eq2 = equals.asSpreader(Object[].class, 2);
assert( (boolean) eq2.invokeExact(new Object[]{ "me", "me" }));
assert(!(boolean) eq2.invokeExact(new Object[]{ "me", "thee" }));
// spread both arguments from a String array:
MethodHandle eq2s = equals.asSpreader(String[].class, 2);
assert( (boolean) eq2s.invokeExact(new String[]{ "me", "me" }));
assert(!(boolean) eq2s.invokeExact(new String[]{ "me", "thee" }));
// spread second arguments from a 1-array:
MethodHandle eq1 = equals.asSpreader(Object[].class, 1);
assert( (boolean) eq1.invokeExact("me", new Object[]{ "me" }));
assert(!(boolean) eq1.invokeExact("me", new Object[]{ "thee" }));
// spread no arguments from a 0-array or null:
MethodHandle eq0 = equals.asSpreader(Object[].class, 0);
assert( (boolean) eq0.invokeExact("me", (Object)"me", new Object[0]));
assert(!(boolean) eq0.invokeExact("me", (Object)"thee", (Object[])null));
// asSpreader and asCollector are approximate inverses:
for (int n = 0; n <= 2; n++) {
for (Class<?> a : new Class<?>[]{Object[].class, String[].class, CharSequence[].class}) {
MethodHandle equals2 = equals.asSpreader(a, n).asCollector(a, n);
assert( (boolean) equals2.invokeWithArguments("me", "me"));
assert(!(boolean) equals2.invokeWithArguments("me", "thee"));
}
}
MethodHandle caToString = publicLookup()
.findStatic(Arrays.class, "toString", methodType(String.class, char[].class));
assertEquals("[A, B, C]", (String) caToString.invokeExact("ABC".toCharArray()));
MethodHandle caString3 = caToString.asCollector(char[].class, 3);
assertEquals("[A, B, C]", (String) caString3.invokeExact('A', 'B', 'C'));
MethodHandle caToString2 = caString3.asSpreader(char[].class, 2);
assertEquals("[A, B, C]", (String) caToString2.invokeExact('A', "BC".toCharArray()));
* </pre></blockquote>
* @param arrayType usually {@code Object[]}, the type of the array argument from which to extract the spread arguments * @param arrayType usually {@code Object[]}, the type of the array argument from which to extract the spread arguments
* @param arrayLength the number of arguments to spread from an incoming array argument * @param arrayLength the number of arguments to spread from an incoming array argument
* @return a new method handle which spreads its final array argument, * @return a new method handle which spreads its final array argument,
* before calling the original method handle * before calling the original method handle
* @throws NullPointerException if {@code arrayType} is a null reference
* @throws IllegalArgumentException if {@code arrayType} is not an array type * @throws IllegalArgumentException if {@code arrayType} is not an array type
* @throws IllegalArgumentException if target does not have at least * @throws IllegalArgumentException if target does not have at least
* {@code arrayLength} parameter types * {@code arrayLength} parameter types,
* or if {@code arrayLength} is negative
* @throws WrongMethodTypeException if the implied {@code asType} call fails * @throws WrongMethodTypeException if the implied {@code asType} call fails
* @see #asCollector * @see #asCollector
*/ */
public MethodHandle asSpreader(Class<?> arrayType, int arrayLength) { public MethodHandle asSpreader(Class<?> arrayType, int arrayLength) {
Class<?> arrayElement = arrayType.getComponentType(); asSpreaderChecks(arrayType, arrayLength);
if (arrayElement == null) throw newIllegalArgumentException("not an array type");
int nargs = type().parameterCount();
if (nargs < arrayLength) throw newIllegalArgumentException("bad spread array length");
return MethodHandleImpl.spreadArguments(this, arrayType, arrayLength); return MethodHandleImpl.spreadArguments(this, arrayType, arrayLength);
} }
private void asSpreaderChecks(Class<?> arrayType, int arrayLength) {
spreadArrayChecks(arrayType, arrayLength);
int nargs = type().parameterCount();
if (nargs < arrayLength || arrayLength < 0)
throw newIllegalArgumentException("bad spread array length");
if (arrayType != Object[].class && arrayLength != 0) {
boolean sawProblem = false;
Class<?> arrayElement = arrayType.getComponentType();
for (int i = nargs - arrayLength; i < nargs; i++) {
if (!MethodType.canConvert(arrayElement, type().parameterType(i))) {
sawProblem = true;
break;
}
}
if (sawProblem) {
ArrayList<Class<?>> ptypes = new ArrayList<Class<?>>(type().parameterList());
for (int i = nargs - arrayLength; i < nargs; i++) {
ptypes.set(i, arrayElement);
}
// elicit an error:
this.asType(MethodType.methodType(type().returnType(), ptypes));
}
}
}
private void spreadArrayChecks(Class<?> arrayType, int arrayLength) {
Class<?> arrayElement = arrayType.getComponentType();
if (arrayElement == null)
throw newIllegalArgumentException("not an array type", arrayType);
if ((arrayLength & 0x7F) != arrayLength) {
if ((arrayLength & 0xFF) != arrayLength)
throw newIllegalArgumentException("array length is not legal", arrayLength);
assert(arrayLength >= 128);
if (arrayElement == long.class ||
arrayElement == double.class)
throw newIllegalArgumentException("array length is not legal for long[] or double[]", arrayLength);
}
}
/** /**
* Makes an adapter which accepts a given number of trailing * Makes an <em>array-collecting</em> method handle, which accepts a given number of trailing
* positional arguments and collects them into an array argument. * positional arguments and collects them into an array argument.
* The new method handle adapts, as its <i>target</i>, * The new method handle adapts, as its <i>target</i>,
* the current method handle. The type of the adapter will be * the current method handle. The type of the adapter will be
@ -785,10 +842,40 @@ public abstract class MethodHandle {
* <p> * <p>
* In order to create a collecting adapter which is not restricted to a particular * In order to create a collecting adapter which is not restricted to a particular
* number of collected arguments, use {@link #asVarargsCollector asVarargsCollector} instead. * number of collected arguments, use {@link #asVarargsCollector asVarargsCollector} instead.
* <p>
* Here are some examples of array-collecting method handles:
* <blockquote><pre>
MethodHandle deepToString = publicLookup()
.findStatic(Arrays.class, "deepToString", methodType(String.class, Object[].class));
assertEquals("[won]", (String) deepToString.invokeExact(new Object[]{"won"}));
MethodHandle ts1 = deepToString.asCollector(Object[].class, 1);
assertEquals(methodType(String.class, Object.class), ts1.type());
//assertEquals("[won]", (String) ts1.invokeExact( new Object[]{"won"})); //FAIL
assertEquals("[[won]]", (String) ts1.invokeExact((Object) new Object[]{"won"}));
// arrayType can be a subtype of Object[]
MethodHandle ts2 = deepToString.asCollector(String[].class, 2);
assertEquals(methodType(String.class, String.class, String.class), ts2.type());
assertEquals("[two, too]", (String) ts2.invokeExact("two", "too"));
MethodHandle ts0 = deepToString.asCollector(Object[].class, 0);
assertEquals("[]", (String) ts0.invokeExact());
// collectors can be nested, Lisp-style
MethodHandle ts22 = deepToString.asCollector(Object[].class, 3).asCollector(String[].class, 2);
assertEquals("[A, B, [C, D]]", ((String) ts22.invokeExact((Object)'A', (Object)"B", "C", "D")));
// arrayType can be any primitive array type
MethodHandle bytesToString = publicLookup()
.findStatic(Arrays.class, "toString", methodType(String.class, byte[].class))
.asCollector(byte[].class, 3);
assertEquals("[1, 2, 3]", (String) bytesToString.invokeExact((byte)1, (byte)2, (byte)3));
MethodHandle longsToString = publicLookup()
.findStatic(Arrays.class, "toString", methodType(String.class, long[].class))
.asCollector(long[].class, 1);
assertEquals("[123]", (String) longsToString.invokeExact((long)123));
* </pre></blockquote>
* @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments * @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments
* @param arrayLength the number of arguments to collect into a new array argument * @param arrayLength the number of arguments to collect into a new array argument
* @return a new method handle which collects some trailing argument * @return a new method handle which collects some trailing argument
* into an array, before calling the original method handle * into an array, before calling the original method handle
* @throws NullPointerException if {@code arrayType} is a null reference
* @throws IllegalArgumentException if {@code arrayType} is not an array type * @throws IllegalArgumentException if {@code arrayType} is not an array type
* or {@code arrayType} is not assignable to this method handle's trailing parameter type, * or {@code arrayType} is not assignable to this method handle's trailing parameter type,
* or {@code arrayLength} is not a legal array size * or {@code arrayLength} is not a legal array size
@ -802,13 +889,16 @@ public abstract class MethodHandle {
return MethodHandleImpl.collectArguments(this, type.parameterCount()-1, collector); return MethodHandleImpl.collectArguments(this, type.parameterCount()-1, collector);
} }
private void asCollectorChecks(Class<?> arrayType, int arrayLength) { // private API: return true if last param exactly matches arrayType
Class<?> arrayElement = arrayType.getComponentType(); private boolean asCollectorChecks(Class<?> arrayType, int arrayLength) {
if (arrayElement == null) spreadArrayChecks(arrayType, arrayLength);
throw newIllegalArgumentException("not an array type", arrayType);
int nargs = type().parameterCount(); int nargs = type().parameterCount();
if (nargs == 0 || !type().parameterType(nargs-1).isAssignableFrom(arrayType)) if (nargs != 0) {
throw newIllegalArgumentException("array type not assignable to trailing argument", this, arrayType); Class<?> lastParam = type().parameterType(nargs-1);
if (lastParam == arrayType) return true;
if (lastParam.isAssignableFrom(arrayType)) return false;
}
throw newIllegalArgumentException("array type not assignable to trailing argument", this, arrayType);
} }
/** /**
@ -825,6 +915,10 @@ public abstract class MethodHandle {
* {@code arrayType}, even if the target has a different * {@code arrayType}, even if the target has a different
* last parameter type. * last parameter type.
* <p> * <p>
* This transformation may return {@code this} if the method handle is
* already of variable arity and its trailing parameter type
* is identical to {@code arrayType}.
* <p>
* When called with {@link #invokeExact invokeExact}, the adapter invokes * When called with {@link #invokeExact invokeExact}, the adapter invokes
* the target with no argument changes. * the target with no argument changes.
* (<em>Note:</em> This behavior is different from a * (<em>Note:</em> This behavior is different from a
@ -841,8 +935,8 @@ public abstract class MethodHandle {
* trailing parameter type of the caller is a reference type identical to * trailing parameter type of the caller is a reference type identical to
* or assignable to the trailing parameter type of the adapter, * or assignable to the trailing parameter type of the adapter,
* the arguments and return values are converted pairwise, * the arguments and return values are converted pairwise,
* as if by {@link MethodHandles#convertArguments convertArguments}. * as if by {@link #asType asType} on a fixed arity
* (This is also normal behavior for {@code invoke} in such a case.) * method handle.
* <p> * <p>
* Otherwise, the arities differ, or the adapter's trailing parameter * Otherwise, the arities differ, or the adapter's trailing parameter
* type is not assignable from the corresponding caller type. * type is not assignable from the corresponding caller type.
@ -910,14 +1004,24 @@ public abstract class MethodHandle {
* <p> * <p>
* Here is an example, of a list-making variable arity method handle: * Here is an example, of a list-making variable arity method handle:
* <blockquote><pre> * <blockquote><pre>
MethodHandle deepToString = publicLookup()
.findStatic(Arrays.class, "deepToString", methodType(String.class, Object[].class));
MethodHandle ts1 = deepToString.asVarargsCollector(Object[].class);
assertEquals("[won]", (String) ts1.invokeExact( new Object[]{"won"}));
assertEquals("[won]", (String) ts1.invoke( new Object[]{"won"}));
assertEquals("[won]", (String) ts1.invoke( "won" ));
assertEquals("[[won]]", (String) ts1.invoke((Object) new Object[]{"won"}));
// findStatic of Arrays.asList(...) produces a variable arity method handle:
MethodHandle asList = publicLookup() MethodHandle asList = publicLookup()
.findStatic(Arrays.class, "asList", methodType(List.class, Object[].class)) .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class));
.asVarargsCollector(Object[].class); assertEquals(methodType(List.class, Object[].class), asList.type());
assert(asList.isVarargsCollector());
assertEquals("[]", asList.invoke().toString()); assertEquals("[]", asList.invoke().toString());
assertEquals("[1]", asList.invoke(1).toString()); assertEquals("[1]", asList.invoke(1).toString());
assertEquals("[two, too]", asList.invoke("two", "too").toString()); assertEquals("[two, too]", asList.invoke("two", "too").toString());
Object[] argv = { "three", "thee", "tee" }; String[] argv = { "three", "thee", "tee" };
assertEquals("[three, thee, tee]", asList.invoke(argv).toString()); assertEquals("[three, thee, tee]", asList.invoke(argv).toString());
assertEquals("[three, thee, tee]", asList.invoke((Object[])argv).toString());
List ls = (List) asList.invoke((Object)argv); List ls = (List) asList.invoke((Object)argv);
assertEquals(1, ls.size()); assertEquals(1, ls.size());
assertEquals("[three, thee, tee]", Arrays.toString((Object[])ls.get(0))); assertEquals("[three, thee, tee]", Arrays.toString((Object[])ls.get(0)));
@ -934,39 +1038,25 @@ assertEquals("[three, thee, tee]", Arrays.toString((Object[])ls.get(0)));
* or not a single trailing argument is interpreted as a whole * or not a single trailing argument is interpreted as a whole
* array or a single element of an array to be collected. * array or a single element of an array to be collected.
* Note that the dynamic type of the trailing argument has no * Note that the dynamic type of the trailing argument has no
* effect on this decision, only a comparison between the static * effect on this decision, only a comparison between the symbolic
* type descriptor of the call site and the type of the method handle.) * type descriptor of the call site and the type descriptor of the method handle.)
* <p style="font-size:smaller;">
* As a result of the previously stated rules, the variable arity behavior
* of a method handle may be suppressed, by binding it to the exact invoker
* of its own type, as follows:
* <blockquote><pre>
MethodHandle vamh = publicLookup()
.findStatic(Arrays.class, "asList", methodType(List.class, Object[].class))
.asVarargsCollector(Object[].class);
MethodHandle mh = MethodHandles.exactInvoker(vamh.type()).bindTo(vamh);
assert(vamh.type().equals(mh.type()));
assertEquals("[1, 2, 3]", vamh.invoke(1,2,3).toString());
boolean failed = false;
try { mh.invoke(1,2,3); }
catch (WrongMethodTypeException ex) { failed = true; }
assert(failed);
* </pre></blockquote>
* This transformation has no behavioral effect if the method handle is
* not of variable arity.
* *
* @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments * @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments
* @return a new method handle which can collect any number of trailing arguments * @return a new method handle which can collect any number of trailing arguments
* into an array, before calling the original method handle * into an array, before calling the original method handle
* @throws NullPointerException if {@code arrayType} is a null reference
* @throws IllegalArgumentException if {@code arrayType} is not an array type * @throws IllegalArgumentException if {@code arrayType} is not an array type
* or {@code arrayType} is not assignable to this method handle's trailing parameter type * or {@code arrayType} is not assignable to this method handle's trailing parameter type
* @see #asCollector * @see #asCollector
* @see #isVarargsCollector * @see #isVarargsCollector
* @see #asFixedArity
*/ */
public MethodHandle asVarargsCollector(Class<?> arrayType) { public MethodHandle asVarargsCollector(Class<?> arrayType) {
Class<?> arrayElement = arrayType.getComponentType(); Class<?> arrayElement = arrayType.getComponentType();
if (arrayElement == null) throw newIllegalArgumentException("not an array type"); boolean lastMatch = asCollectorChecks(arrayType, 0);
return MethodHandles.asVarargsCollector(this, arrayType); if (isVarargsCollector() && lastMatch)
return this;
return AdapterMethodHandle.makeVarargsCollector(this, arrayType);
} }
/** /**
@ -982,11 +1072,60 @@ assert(failed);
* </ul> * </ul>
* @return true if this method handle accepts more than one arity of plain, inexact {@code invoke} calls * @return true if this method handle accepts more than one arity of plain, inexact {@code invoke} calls
* @see #asVarargsCollector * @see #asVarargsCollector
* @see #asFixedArity
*/ */
public boolean isVarargsCollector() { public boolean isVarargsCollector() {
return false; return false;
} }
/**
* Makes a <em>fixed arity</em> method handle which is otherwise
* equivalent to the the current method handle.
* <p>
* If the current method handle is not of
* {@linkplain #asVarargsCollector variable arity},
* the current method handle is returned.
* This is true even if the current method handle
* could not be a valid input to {@code asVarargsCollector}.
* <p>
* Otherwise, the resulting fixed-arity method handle has the same
* type and behavior of the current method handle,
* except that {@link #isVarargsCollector isVarargsCollector}
* will be false.
* The fixed-arity method handle may (or may not) be the
* a previous argument to {@code asVarargsCollector}.
* <p>
* Here is an example, of a list-making variable arity method handle:
* <blockquote><pre>
MethodHandle asListVar = publicLookup()
.findStatic(Arrays.class, "asList", methodType(List.class, Object[].class))
.asVarargsCollector(Object[].class);
MethodHandle asListFix = asListVar.asFixedArity();
assertEquals("[1]", asListVar.invoke(1).toString());
Exception caught = null;
try { asListFix.invoke((Object)1); }
catch (Exception ex) { caught = ex; }
assert(caught instanceof ClassCastException);
assertEquals("[two, too]", asListVar.invoke("two", "too").toString());
try { asListFix.invoke("two", "too"); }
catch (Exception ex) { caught = ex; }
assert(caught instanceof WrongMethodTypeException);
Object[] argv = { "three", "thee", "tee" };
assertEquals("[three, thee, tee]", asListVar.invoke(argv).toString());
assertEquals("[three, thee, tee]", asListFix.invoke(argv).toString());
assertEquals(1, ((List) asListVar.invoke((Object)argv)).size());
assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString());
* </pre></blockquote>
*
* @return a new method handle which accepts only a fixed number of arguments
* @see #asVarargsCollector
* @see #isVarargsCollector
*/
public MethodHandle asFixedArity() {
assert(!isVarargsCollector());
return this;
}
/** /**
* Binds a value {@code x} to the first argument of a method handle, without invoking it. * Binds a value {@code x} to the first argument of a method handle, without invoking it.
* The new method handle adapts, as its <i>target</i>, * The new method handle adapts, as its <i>target</i>,
@ -1043,6 +1182,12 @@ assert(failed);
*/ */
@Override @Override
public String toString() { public String toString() {
if (DEBUG_METHOD_HANDLE_NAMES) return debugString();
return "MethodHandle"+type;
}
/*non-public*/
String debugString() {
return getNameString(this); return getNameString(this);
} }
} }

View File

@ -26,6 +26,8 @@
package java.lang.invoke; package java.lang.invoke;
import sun.invoke.util.VerifyType; import sun.invoke.util.VerifyType;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
@ -82,20 +84,44 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
} }
DirectMethodHandle mh = new DirectMethodHandle(mtype, method, doDispatch, lookupClass); DirectMethodHandle mh = new DirectMethodHandle(mtype, method, doDispatch, lookupClass);
if (!mh.isValid()) if (!mh.isValid())
throw method.makeAccessException("no access", lookupClass); throw method.makeAccessException("no direct method handle", lookupClass);
assert(mh.type() == mtype); assert(mh.type() == mtype);
if (!method.isVarargs()) if (!method.isVarargs())
return mh; return mh;
else int argc = mtype.parameterCount();
return mh.asVarargsCollector(mtype.parameterType(mtype.parameterCount()-1)); if (argc != 0) {
Class<?> arrayType = mtype.parameterType(argc-1);
if (arrayType.isArray())
return AdapterMethodHandle.makeVarargsCollector(mh, arrayType);
}
throw method.makeAccessException("cannot make variable arity", null);
} }
static static
MethodHandle makeAllocator(MethodHandle rawConstructor) { MethodHandle makeAllocator(MethodHandle rawConstructor) {
MethodType rawConType = rawConstructor.type(); MethodType rawConType = rawConstructor.type();
Class<?> allocateClass = rawConType.parameterType(0);
// Wrap the raw (unsafe) constructor with the allocation of a suitable object. // Wrap the raw (unsafe) constructor with the allocation of a suitable object.
if (AdapterMethodHandle.canCollectArguments(rawConType, MethodType.methodType(allocateClass), 0, true)) {
// allocator(arg...)
// [fold]=> cookedConstructor(obj=allocate(C), arg...)
// [dup,collect]=> identity(obj, void=rawConstructor(obj, arg...))
MethodHandle returner = MethodHandles.identity(allocateClass);
MethodType ctype = rawConType.insertParameterTypes(0, allocateClass).changeReturnType(allocateClass);
MethodHandle cookedConstructor = AdapterMethodHandle.makeCollectArguments(returner, rawConstructor, 1, false);
assert(cookedConstructor.type().equals(ctype));
ctype = ctype.dropParameterTypes(0, 1);
cookedConstructor = AdapterMethodHandle.makeCollectArguments(cookedConstructor, returner, 0, true);
MethodHandle allocator = new AllocateObject(allocateClass);
// allocate() => new C(void)
assert(allocator.type().equals(MethodType.methodType(allocateClass)));
ctype = ctype.dropParameterTypes(0, 1);
MethodHandle fold = foldArguments(cookedConstructor, ctype, 0, allocator);
return fold;
}
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
MethodHandle allocator MethodHandle allocator
= AllocateObject.make(rawConType.parameterType(0), rawConstructor); = AllocateObject.make(allocateClass, rawConstructor);
assert(allocator.type() assert(allocator.type()
.equals(rawConType.dropParameterTypes(0, 1).changeReturnType(rawConType.parameterType(0)))); .equals(rawConType.dropParameterTypes(0, 1).changeReturnType(rawConType.parameterType(0))));
return allocator; return allocator;
@ -112,8 +138,16 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
super(invoker); super(invoker);
this.allocateClass = allocateClass; this.allocateClass = allocateClass;
this.rawConstructor = rawConstructor; this.rawConstructor = rawConstructor;
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
}
// for allocation only:
private AllocateObject(Class<C> allocateClass) {
super(ALLOCATE.asType(MethodType.methodType(allocateClass, AllocateObject.class)));
this.allocateClass = allocateClass;
this.rawConstructor = null;
} }
static MethodHandle make(Class<?> allocateClass, MethodHandle rawConstructor) { static MethodHandle make(Class<?> allocateClass, MethodHandle rawConstructor) {
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
MethodType rawConType = rawConstructor.type(); MethodType rawConType = rawConstructor.type();
assert(rawConType.parameterType(0) == allocateClass); assert(rawConType.parameterType(0) == allocateClass);
MethodType newType = rawConType.dropParameterTypes(0, 1).changeReturnType(allocateClass); MethodType newType = rawConType.dropParameterTypes(0, 1).changeReturnType(allocateClass);
@ -129,14 +163,14 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
} else { } else {
MethodHandle invoke = VARARGS_INVOKE; MethodHandle invoke = VARARGS_INVOKE;
MethodType conType = CON_TYPES[nargs]; MethodType conType = CON_TYPES[nargs];
MethodHandle gcon = spreadArguments(rawConstructor, conType, 1); MethodHandle gcon = spreadArgumentsFromPos(rawConstructor, conType, 1);
if (gcon == null) return null; if (gcon == null) return null;
MethodHandle galloc = new AllocateObject(invoke, allocateClass, gcon); MethodHandle galloc = new AllocateObject(invoke, allocateClass, gcon);
return collectArguments(galloc, newType, 1, null); return collectArguments(galloc, newType, 1, null);
} }
} }
@Override @Override
public String toString() { String debugString() {
return addTypeString(allocateClass.getSimpleName(), this); return addTypeString(allocateClass.getSimpleName(), this);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -214,9 +248,11 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
// For testing use this: // For testing use this:
//static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2); //static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2);
static final MethodHandle VARARGS_INVOKE; static final MethodHandle VARARGS_INVOKE;
static final MethodHandle ALLOCATE;
static { static {
try { try {
VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(AllocateObject.class, "invoke_V", MethodType.genericMethodType(0, true)); VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(AllocateObject.class, "invoke_V", MethodType.genericMethodType(0, true));
ALLOCATE = IMPL_LOOKUP.findVirtual(AllocateObject.class, "allocate", MethodType.genericMethodType(0));
} catch (ReflectiveOperationException ex) { } catch (ReflectiveOperationException ex) {
throw uncaughtException(ex); throw uncaughtException(ex);
} }
@ -278,7 +314,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
this.base = staticBase(field); this.base = staticBase(field);
} }
@Override @Override
public String toString() { return addTypeString(name, this); } String debugString() { return addTypeString(name, this); }
int getFieldI(C obj) { return unsafe.getInt(obj, offset); } int getFieldI(C obj) { return unsafe.getInt(obj, offset); }
void setFieldI(C obj, int x) { unsafe.putInt(obj, offset, x); } void setFieldI(C obj, int x) { unsafe.putInt(obj, offset, x); }
@ -302,17 +338,20 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
void setFieldL(C obj, V x) { unsafe.putObject(obj, offset, x); } void setFieldL(C obj, V x) { unsafe.putObject(obj, offset, x); }
// cast (V) is OK here, since we wrap convertArguments around the MH. // cast (V) is OK here, since we wrap convertArguments around the MH.
static Object staticBase(MemberName field) { static Object staticBase(final MemberName field) {
if (!field.isStatic()) return null; if (!field.isStatic()) return null;
Class c = field.getDeclaringClass(); return AccessController.doPrivileged(new PrivilegedAction<Object>() {
java.lang.reflect.Field f; public Object run() {
try { try {
// FIXME: Should not have to create 'f' to get this value. Class c = field.getDeclaringClass();
f = c.getDeclaredField(field.getName()); // FIXME: Should not have to create 'f' to get this value.
return unsafe.staticFieldBase(f); java.lang.reflect.Field f = c.getDeclaredField(field.getName());
} catch (Exception ee) { return unsafe.staticFieldBase(f);
throw uncaughtException(ee); } catch (NoSuchFieldException ee) {
} throw uncaughtException(ee);
}
}
});
} }
int getStaticI() { return unsafe.getInt(base, offset); } int getStaticI() { return unsafe.getInt(base, offset); }
@ -455,14 +494,14 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
*/ */
static static
MethodHandle bindReceiver(MethodHandle target, Object receiver) { MethodHandle bindReceiver(MethodHandle target, Object receiver) {
if (receiver == null) return null;
if (target instanceof AdapterMethodHandle && if (target instanceof AdapterMethodHandle &&
((AdapterMethodHandle)target).conversionOp() == MethodHandleNatives.Constants.OP_RETYPE_ONLY ((AdapterMethodHandle)target).conversionOp() == MethodHandleNatives.Constants.OP_RETYPE_ONLY
) { ) {
Object info = MethodHandleNatives.getTargetInfo(target); Object info = MethodHandleNatives.getTargetInfo(target);
if (info instanceof DirectMethodHandle) { if (info instanceof DirectMethodHandle) {
DirectMethodHandle dmh = (DirectMethodHandle) info; DirectMethodHandle dmh = (DirectMethodHandle) info;
if (receiver == null || if (dmh.type().parameterType(0).isAssignableFrom(receiver.getClass())) {
dmh.type().parameterType(0).isAssignableFrom(receiver.getClass())) {
MethodHandle bmh = new BoundMethodHandle(dmh, receiver, 0); MethodHandle bmh = new BoundMethodHandle(dmh, receiver, 0);
MethodType newType = target.type().dropParameterTypes(0, 1); MethodType newType = target.type().dropParameterTypes(0, 1);
return convertArguments(bmh, newType, bmh.type(), 0); return convertArguments(bmh, newType, bmh.type(), 0);
@ -668,7 +707,9 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
if (target == null) throw newIllegalArgumentException("cannot drop"); if (target == null) throw newIllegalArgumentException("cannot drop");
oldType = target.type(); oldType = target.type();
} }
return convertArguments(target, newType, oldType, 0); target = convertArguments(target, newType, oldType, 0);
assert(target != null);
return target;
} }
/*non-public*/ static /*non-public*/ static
@ -747,7 +788,8 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
.insertParameterTypes(keepPosArgs, arrayType); .insertParameterTypes(keepPosArgs, arrayType);
return spreadArguments(target, newType, keepPosArgs, arrayType, arrayLength); return spreadArguments(target, newType, keepPosArgs, arrayType, arrayLength);
} }
static MethodHandle spreadArguments(MethodHandle target, MethodType newType, int spreadArgPos) { // called internally only
static MethodHandle spreadArgumentsFromPos(MethodHandle target, MethodType newType, int spreadArgPos) {
int arrayLength = target.type().parameterCount() - spreadArgPos; int arrayLength = target.type().parameterCount() - spreadArgPos;
return spreadArguments(target, newType, spreadArgPos, Object[].class, arrayLength); return spreadArguments(target, newType, spreadArgPos, Object[].class, arrayLength);
} }
@ -761,9 +803,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
// spread the last argument of newType to oldType // spread the last argument of newType to oldType
assert(arrayLength == oldType.parameterCount() - spreadArgPos); assert(arrayLength == oldType.parameterCount() - spreadArgPos);
assert(newType.parameterType(spreadArgPos) == arrayType); assert(newType.parameterType(spreadArgPos) == arrayType);
MethodHandle res = AdapterMethodHandle.makeSpreadArguments(newType, target, arrayType, spreadArgPos, arrayLength); return AdapterMethodHandle.makeSpreadArguments(newType, target, arrayType, spreadArgPos, arrayLength);
if (res == null) throw new IllegalArgumentException("spread on "+target+" with "+arrayType.getSimpleName());
return res;
} }
static MethodHandle collectArguments(MethodHandle target, static MethodHandle collectArguments(MethodHandle target,
@ -771,6 +811,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
MethodHandle collector) { MethodHandle collector) {
MethodType type = target.type(); MethodType type = target.type();
Class<?> collectType = collector.type().returnType(); Class<?> collectType = collector.type().returnType();
assert(collectType != void.class); // else use foldArguments
if (collectType != type.parameterType(collectArg)) if (collectType != type.parameterType(collectArg))
target = target.asType(type.changeParameterType(collectArg, collectType)); target = target.asType(type.changeParameterType(collectArg, collectType));
MethodType newType = type MethodType newType = type
@ -809,6 +850,12 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
MethodType ttype = target.type(); MethodType ttype = target.type();
MethodType ftype = filter.type(); MethodType ftype = filter.type();
assert(ftype.parameterCount() == 1); assert(ftype.parameterCount() == 1);
MethodHandle result = null;
if (AdapterMethodHandle.canCollectArguments(ttype, ftype, pos, false)) {
result = AdapterMethodHandle.makeCollectArguments(target, filter, pos, false);
if (result != null) return result;
}
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
MethodType rtype = ttype.changeParameterType(pos, ftype.parameterType(0)); MethodType rtype = ttype.changeParameterType(pos, ftype.parameterType(0));
MethodType gttype = ttype.generic(); MethodType gttype = ttype.generic();
if (ttype != gttype) { if (ttype != gttype) {
@ -820,18 +867,11 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
filter = convertArguments(filter, gftype, ftype, 0); filter = convertArguments(filter, gftype, ftype, 0);
ftype = gftype; ftype = gftype;
} }
MethodHandle result = null; if (ftype == ttype) {
if (AdapterMethodHandle.canCollectArguments(ttype, ftype, pos, false)) {
result = AdapterMethodHandle.makeCollectArguments(target, filter, pos, false);
}
if (result == null) {
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
if (ftype == ttype) {
// simple unary case // simple unary case
result = FilterOneArgument.make(filter, target); result = FilterOneArgument.make(filter, target);
} else { } else {
result = FilterGeneric.makeArgumentFilter(pos, filter, target); result = FilterGeneric.makeArgumentFilter(pos, filter, target);
}
} }
if (result.type() != rtype) if (result.type() != rtype)
result = result.asType(rtype); result = result.asType(rtype);
@ -879,34 +919,40 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
this.target = target; this.target = target;
this.fallback = fallback; this.fallback = fallback;
} }
// FIXME: Build the control flow out of foldArguments. static boolean preferRicochetFrame(MethodType type) {
return true; // always use RF if available
}
static MethodHandle make(MethodHandle test, MethodHandle target, MethodHandle fallback) { static MethodHandle make(MethodHandle test, MethodHandle target, MethodHandle fallback) {
MethodType type = target.type(); MethodType type = target.type();
int nargs = type.parameterCount(); int nargs = type.parameterCount();
if (nargs < INVOKES.length) { if (nargs < INVOKES.length) {
if (preferRicochetFrame(type))
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
MethodHandle invoke = INVOKES[nargs]; MethodHandle invoke = INVOKES[nargs];
MethodType gtype = type.generic(); MethodType gtype = type.generic();
assert(invoke.type().dropParameterTypes(0,1) == gtype); assert(invoke.type().dropParameterTypes(0,1) == gtype);
MethodHandle gtest = convertArguments(test, gtype.changeReturnType(boolean.class), test.type(), 0); // Note: convertArguments(...2) avoids interface casts present in convertArguments(...0)
MethodHandle gtarget = convertArguments(target, gtype, type, 0); MethodHandle gtest = convertArguments(test, gtype.changeReturnType(boolean.class), test.type(), 2);
MethodHandle gfallback = convertArguments(fallback, gtype, type, 0); MethodHandle gtarget = convertArguments(target, gtype, type, 2);
MethodHandle gfallback = convertArguments(fallback, gtype, type, 2);
if (gtest == null || gtarget == null || gfallback == null) return null; if (gtest == null || gtarget == null || gfallback == null) return null;
MethodHandle gguard = new GuardWithTest(invoke, gtest, gtarget, gfallback); MethodHandle gguard = new GuardWithTest(invoke, gtest, gtarget, gfallback);
return convertArguments(gguard, type, gtype, 0); return convertArguments(gguard, type, gtype, 2);
} else { } else {
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
MethodHandle invoke = VARARGS_INVOKE; MethodHandle invoke = VARARGS_INVOKE;
MethodType gtype = MethodType.genericMethodType(1); MethodType gtype = MethodType.genericMethodType(1);
assert(invoke.type().dropParameterTypes(0,1) == gtype); assert(invoke.type().dropParameterTypes(0,1) == gtype);
MethodHandle gtest = spreadArguments(test, gtype.changeReturnType(boolean.class), 0); MethodHandle gtest = spreadArgumentsFromPos(test, gtype.changeReturnType(boolean.class), 0);
MethodHandle gtarget = spreadArguments(target, gtype, 0); MethodHandle gtarget = spreadArgumentsFromPos(target, gtype, 0);
MethodHandle gfallback = spreadArguments(fallback, gtype, 0); MethodHandle gfallback = spreadArgumentsFromPos(fallback, gtype, 0);
MethodHandle gguard = new GuardWithTest(invoke, gtest, gtarget, gfallback); MethodHandle gguard = new GuardWithTest(invoke, gtest, gtarget, gfallback);
if (gtest == null || gtarget == null || gfallback == null) return null; if (gtest == null || gtarget == null || gfallback == null) return null;
return collectArguments(gguard, type, 0, null); return collectArguments(gguard, type, 0, null);
} }
} }
@Override @Override
public String toString() { String debugString() {
return addTypeString(target, this); return addTypeString(target, this);
} }
private Object invoke_V(Object... av) throws Throwable { private Object invoke_V(Object... av) throws Throwable {
@ -989,10 +1035,50 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
} }
} }
static
MethodHandle selectAlternative(boolean testResult, MethodHandle target, MethodHandle fallback) {
return testResult ? target : fallback;
}
static MethodHandle SELECT_ALTERNATIVE;
static MethodHandle selectAlternative() {
if (SELECT_ALTERNATIVE != null) return SELECT_ALTERNATIVE;
try {
SELECT_ALTERNATIVE
= IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "selectAlternative",
MethodType.methodType(MethodHandle.class, boolean.class, MethodHandle.class, MethodHandle.class));
} catch (ReflectiveOperationException ex) {
throw new RuntimeException(ex);
}
return SELECT_ALTERNATIVE;
}
static static
MethodHandle makeGuardWithTest(MethodHandle test, MethodHandle makeGuardWithTest(MethodHandle test,
MethodHandle target, MethodHandle target,
MethodHandle fallback) { MethodHandle fallback) {
// gwt(arg...)
// [fold]=> continueAfterTest(z=test(arg...), arg...)
// [filter]=> (tf=select(z))(arg...)
// where select(z) = select(z, t, f).bindTo(t, f) => z ? t f
// [tailcall]=> tf(arg...)
assert(test.type().returnType() == boolean.class);
MethodType targetType = target.type();
MethodType foldTargetType = targetType.insertParameterTypes(0, boolean.class);
if (AdapterMethodHandle.canCollectArguments(foldTargetType, test.type(), 0, true)
&& GuardWithTest.preferRicochetFrame(targetType)) {
// working backwards, as usual:
assert(target.type().equals(fallback.type()));
MethodHandle tailcall = MethodHandles.exactInvoker(target.type());
MethodHandle select = selectAlternative();
select = bindArgument(select, 2, fallback);
select = bindArgument(select, 1, target);
// select(z: boolean) => (z ? target : fallback)
MethodHandle filter = filterArgument(tailcall, 0, select);
assert(filter.type().parameterType(0) == boolean.class);
MethodHandle fold = foldArguments(filter, filter.type().dropParameterTypes(0, 1), 0, test);
return fold;
}
return GuardWithTest.make(test, target, fallback); return GuardWithTest.make(test, target, fallback);
} }
@ -1012,7 +1098,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
this.catcher = catcher; this.catcher = catcher;
} }
@Override @Override
public String toString() { String debugString() {
return addTypeString(target, this); return addTypeString(target, this);
} }
private Object invoke_V(Object... av) throws Throwable { private Object invoke_V(Object... av) throws Throwable {
@ -1136,19 +1222,21 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
if (nargs < GuardWithCatch.INVOKES.length) { if (nargs < GuardWithCatch.INVOKES.length) {
MethodType gtype = type.generic(); MethodType gtype = type.generic();
MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class); MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class);
MethodHandle gtarget = convertArguments(target, gtype, type, 0); // Note: convertArguments(...2) avoids interface casts present in convertArguments(...0)
MethodHandle gcatcher = convertArguments(catcher, gcatchType, ctype, 0); MethodHandle gtarget = convertArguments(target, gtype, type, 2);
MethodHandle gcatcher = convertArguments(catcher, gcatchType, ctype, 2);
MethodHandle gguard = new GuardWithCatch(gtarget, exType, gcatcher); MethodHandle gguard = new GuardWithCatch(gtarget, exType, gcatcher);
if (gtarget == null || gcatcher == null || gguard == null) return null; if (gtarget == null || gcatcher == null || gguard == null) return null;
return convertArguments(gguard, type, gtype, 0); return convertArguments(gguard, type, gtype, 2);
} else { } else {
MethodType gtype = MethodType.genericMethodType(0, true); MethodType gtype = MethodType.genericMethodType(0, true);
MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class); MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class);
MethodHandle gtarget = spreadArguments(target, gtype, 0); MethodHandle gtarget = spreadArgumentsFromPos(target, gtype, 0);
MethodHandle gcatcher = spreadArguments(catcher, gcatchType, 1); catcher = catcher.asType(ctype.changeParameterType(0, Throwable.class));
MethodHandle gcatcher = spreadArgumentsFromPos(catcher, gcatchType, 1);
MethodHandle gguard = new GuardWithCatch(GuardWithCatch.VARARGS_INVOKE, gtarget, exType, gcatcher); MethodHandle gguard = new GuardWithCatch(GuardWithCatch.VARARGS_INVOKE, gtarget, exType, gcatcher);
if (gtarget == null || gcatcher == null || gguard == null) return null; if (gtarget == null || gcatcher == null || gguard == null) return null;
return collectArguments(gguard, type, 0, null); return collectArguments(gguard, type, 0, ValueConversions.varargsArray(nargs)).asType(type);
} }
} }
@ -1178,8 +1266,4 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
static MethodHandle getBootstrap(Class<?> callerClass) { static MethodHandle getBootstrap(Class<?> callerClass) {
return MethodHandleNatives.getBootstrap(callerClass); return MethodHandleNatives.getBootstrap(callerClass);
} }
static MethodHandle asVarargsCollector(MethodHandle target, Class<?> arrayType) {
return AdapterMethodHandle.makeVarargsCollector(target, arrayType);
}
} }

View File

@ -118,32 +118,20 @@ class MethodHandleNatives {
/** Derived mode flag. Only false on some old JVM implementations. */ /** Derived mode flag. Only false on some old JVM implementations. */
static final boolean HAVE_RICOCHET_FRAMES; static final boolean HAVE_RICOCHET_FRAMES;
static final int OP_ROT_ARGS_DOWN_LIMIT_BIAS;
private static native void registerNatives(); private static native void registerNatives();
static { static {
int JVM_PUSH_LIMIT_; registerNatives();
int JVM_STACK_MOVE_UNIT_; int k;
int CONV_OP_IMPLEMENTED_MASK_; JVM_PUSH_LIMIT = getConstant(Constants.GC_JVM_PUSH_LIMIT);
try { JVM_STACK_MOVE_UNIT = getConstant(Constants.GC_JVM_STACK_MOVE_UNIT);
registerNatives(); k = getConstant(Constants.GC_CONV_OP_IMPLEMENTED_MASK);
JVM_PUSH_LIMIT_ = getConstant(Constants.GC_JVM_PUSH_LIMIT); CONV_OP_IMPLEMENTED_MASK = (k != 0) ? k : DEFAULT_CONV_OP_IMPLEMENTED_MASK;
JVM_STACK_MOVE_UNIT_ = getConstant(Constants.GC_JVM_STACK_MOVE_UNIT); k = getConstant(Constants.GC_OP_ROT_ARGS_DOWN_LIMIT_BIAS);
CONV_OP_IMPLEMENTED_MASK_ = getConstant(Constants.GC_CONV_OP_IMPLEMENTED_MASK); OP_ROT_ARGS_DOWN_LIMIT_BIAS = (k != 0) ? (byte)k : -1;
//sun.reflect.Reflection.registerMethodsToFilter(MethodHandleImpl.class, "init"); HAVE_RICOCHET_FRAMES = (CONV_OP_IMPLEMENTED_MASK & (1<<OP_COLLECT_ARGS)) != 0;
} catch (UnsatisfiedLinkError ee) { //sun.reflect.Reflection.registerMethodsToFilter(MethodHandleImpl.class, "init");
// ignore; if we use init() methods later we'll see linkage errors
JVM_PUSH_LIMIT_ = 3; // arbitrary
JVM_STACK_MOVE_UNIT_ = -1; // arbitrary
CONV_OP_IMPLEMENTED_MASK_ = 0;
JVM_PUSH_LIMIT = JVM_PUSH_LIMIT_;
JVM_STACK_MOVE_UNIT = JVM_STACK_MOVE_UNIT_;
throw ee; // just die; hopeless to try to run with an older JVM
}
JVM_PUSH_LIMIT = JVM_PUSH_LIMIT_;
JVM_STACK_MOVE_UNIT = JVM_STACK_MOVE_UNIT_;
if (CONV_OP_IMPLEMENTED_MASK_ == 0)
CONV_OP_IMPLEMENTED_MASK_ = DEFAULT_CONV_OP_IMPLEMENTED_MASK;
CONV_OP_IMPLEMENTED_MASK = CONV_OP_IMPLEMENTED_MASK_;
HAVE_RICOCHET_FRAMES = (CONV_OP_IMPLEMENTED_MASK & (1<<OP_COLLECT_ARGS)) != 0;
} }
// All compile-time constants go here. // All compile-time constants go here.
@ -154,7 +142,8 @@ class MethodHandleNatives {
static final int // for getConstant static final int // for getConstant
GC_JVM_PUSH_LIMIT = 0, GC_JVM_PUSH_LIMIT = 0,
GC_JVM_STACK_MOVE_UNIT = 1, GC_JVM_STACK_MOVE_UNIT = 1,
GC_CONV_OP_IMPLEMENTED_MASK = 2; GC_CONV_OP_IMPLEMENTED_MASK = 2,
GC_OP_ROT_ARGS_DOWN_LIMIT_BIAS = 3;
static final int static final int
ETF_HANDLE_OR_METHOD_NAME = 0, // all available data (immediate MH or method) ETF_HANDLE_OR_METHOD_NAME = 0, // all available data (immediate MH or method)
ETF_DIRECT_HANDLE = 1, // ultimate method handle (will be a DMH, may be self) ETF_DIRECT_HANDLE = 1, // ultimate method handle (will be a DMH, may be self)
@ -359,6 +348,12 @@ class MethodHandleNatives {
required = Object[].class; // should have been an array required = Object[].class; // should have been an array
code = 192; // checkcast code = 192; // checkcast
break; break;
case 191: // athrow
// JVM is asking us to wrap an exception which happened during resolving
if (required == BootstrapMethodError.class) {
throw new BootstrapMethodError((Throwable) actual);
}
break;
} }
// disregard the identity of the actual object, if it is not a class: // disregard the identity of the actual object, if it is not a class:
if (message == null) { if (message == null) {
@ -389,18 +384,7 @@ class MethodHandleNatives {
Class<?> defc, String name, Object type) { Class<?> defc, String name, Object type) {
try { try {
Lookup lookup = IMPL_LOOKUP.in(callerClass); Lookup lookup = IMPL_LOOKUP.in(callerClass);
switch (refKind) { return lookup.linkMethodHandleConstant(refKind, defc, name, type);
case REF_getField: return lookup.findGetter( defc, name, (Class<?>) type );
case REF_getStatic: return lookup.findStaticGetter( defc, name, (Class<?>) type );
case REF_putField: return lookup.findSetter( defc, name, (Class<?>) type );
case REF_putStatic: return lookup.findStaticSetter( defc, name, (Class<?>) type );
case REF_invokeVirtual: return lookup.findVirtual( defc, name, (MethodType) type );
case REF_invokeStatic: return lookup.findStatic( defc, name, (MethodType) type );
case REF_invokeSpecial: return lookup.findSpecial( defc, name, (MethodType) type, callerClass );
case REF_newInvokeSpecial: return lookup.findConstructor( defc, (MethodType) type );
case REF_invokeInterface: return lookup.findVirtual( defc, name, (MethodType) type );
}
throw new IllegalArgumentException("bad MethodHandle constant "+name+" : "+type);
} catch (ReflectiveOperationException ex) { } catch (ReflectiveOperationException ex) {
Error err = new IncompatibleClassChangeError(); Error err = new IncompatibleClassChangeError();
err.initCause(ex); err.initCause(ex);

View File

@ -0,0 +1,257 @@
/*
* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute 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.invoke;
import java.lang.reflect.*;
import sun.invoke.WrapperInstance;
/**
* This class consists exclusively of static methods that help adapt
* method handles to other JVM types, such as interfaces.
*/
public class MethodHandleProxies {
private MethodHandleProxies() { } // do not instantiate
/**
* Produces an instance of the given single-method interface which redirects
* its calls to the given method handle.
* <p>
* A single-method interface is an interface which declares a uniquely named method.
* When determining the uniquely named method of a single-method interface,
* the public {@code Object} methods ({@code toString}, {@code equals}, {@code hashCode})
* are disregarded. For example, {@link java.util.Comparator} is a single-method interface,
* even though it re-declares the {@code Object.equals} method.
* <p>
* The interface must be public. No additional access checks are performed.
* <p>
* The resulting instance of the required type will respond to
* invocation of the type's uniquely named method by calling
* the given target on the incoming arguments,
* and returning or throwing whatever the target
* returns or throws. The invocation will be as if by
* {@code target.invoke}.
* The target's type will be checked before the
* instance is created, as if by a call to {@code asType},
* which may result in a {@code WrongMethodTypeException}.
* <p>
* The uniquely named method is allowed to be multiply declared,
* with distinct type descriptors. (E.g., it can be overloaded,
* or can possess bridge methods.) All such declarations are
* connected directly to the target method handle.
* Argument and return types are adjusted by {@code asType}
* for each individual declaration.
* <p>
* The wrapper instance will implement the requested interface
* and its super-types, but no other single-method interfaces.
* This means that the instance will not unexpectedly
* pass an {@code instanceof} test for any unrequested type.
* <p style="font-size:smaller;">
* <em>Implementation Note:</em>
* Therefore, each instance must implement a unique single-method interface.
* Implementations may not bundle together
* multiple single-method interfaces onto single implementation classes
* in the style of {@link java.awt.AWTEventMulticaster}.
* <p>
* The method handle may throw an <em>undeclared exception</em>,
* which means any checked exception (or other checked throwable)
* not declared by the requested type's single abstract method.
* If this happens, the throwable will be wrapped in an instance of
* {@link java.lang.reflect.UndeclaredThrowableException UndeclaredThrowableException}
* and thrown in that wrapped form.
* <p>
* Like {@link java.lang.Integer#valueOf Integer.valueOf},
* {@code asInterfaceInstance} is a factory method whose results are defined
* by their behavior.
* It is not guaranteed to return a new instance for every call.
* <p>
* Because of the possibility of {@linkplain java.lang.reflect.Method#isBridge bridge methods}
* and other corner cases, the interface may also have several abstract methods
* with the same name but having distinct descriptors (types of returns and parameters).
* In this case, all the methods are bound in common to the one given target.
* The type check and effective {@code asType} conversion is applied to each
* method type descriptor, and all abstract methods are bound to the target in common.
* Beyond this type check, no further checks are made to determine that the
* abstract methods are related in any way.
* <p>
* Future versions of this API may accept additional types,
* such as abstract classes with single abstract methods.
* Future versions of this API may also equip wrapper instances
* with one or more additional public "marker" interfaces.
*
* @param target the method handle to invoke from the wrapper
* @param intfc the desired type of the wrapper, a single-method interface
* @return a correctly-typed wrapper for the given target
* @throws NullPointerException if either argument is null
* @throws IllegalArgumentException if the {@code intfc} is not a
* valid argument to this method
* @throws WrongMethodTypeException if the target cannot
* be converted to the type required by the requested interface
*/
// Other notes to implementors:
// <p>
// No stable mapping is promised between the single-method interface and
// the implementation class C. Over time, several implementation
// classes might be used for the same type.
// <p>
// If the implementation is able
// to prove that a wrapper of the required type
// has already been created for a given
// method handle, or for another method handle with the
// same behavior, the implementation may return that wrapper in place of
// a new wrapper.
// <p>
// This method is designed to apply to common use cases
// where a single method handle must interoperate with
// an interface that implements a function-like
// API. Additional variations, such as single-abstract-method classes with
// private constructors, or interfaces with multiple but related
// entry points, must be covered by hand-written or automatically
// generated adapter classes.
//
public static
<T> T asInterfaceInstance(final Class<T> intfc, final MethodHandle target) {
// POC implementation only; violates the above contract several ways
final Method sm = getSingleMethod(intfc);
if (sm == null)
throw new IllegalArgumentException("not a single-method interface: "+intfc.getName());
MethodType smMT = MethodType.methodType(sm.getReturnType(), sm.getParameterTypes());
MethodHandle checkTarget = target.asType(smMT); // make throw WMT
checkTarget = checkTarget.asType(checkTarget.type().changeReturnType(Object.class));
final MethodHandle vaTarget = checkTarget.asSpreader(Object[].class, smMT.parameterCount());
return intfc.cast(Proxy.newProxyInstance(
intfc.getClassLoader(),
new Class[]{ intfc, WrapperInstance.class },
new InvocationHandler() {
private Object getArg(String name) {
if ((Object)name == "getWrapperInstanceTarget") return target;
if ((Object)name == "getWrapperInstanceType") return intfc;
throw new AssertionError();
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getDeclaringClass() == WrapperInstance.class)
return getArg(method.getName());
if (method.equals(sm))
return vaTarget.invokeExact(args);
if (isObjectMethod(method))
return callObjectMethod(this, method, args);
throw new InternalError();
}
}));
}
/**
* Determines if the given object was produced by a call to {@link #asInterfaceInstance asInterfaceInstance}.
* @param x any reference
* @return true if the reference is not null and points to an object produced by {@code asInterfaceInstance}
*/
public static
boolean isWrapperInstance(Object x) {
return x instanceof WrapperInstance;
}
private static WrapperInstance asWrapperInstance(Object x) {
try {
if (x != null)
return (WrapperInstance) x;
} catch (ClassCastException ex) {
}
throw new IllegalArgumentException("not a wrapper instance");
}
/**
* Produces or recovers a target method handle which is behaviorally
* equivalent to the unique method of this wrapper instance.
* The object {@code x} must have been produced by a call to {@link #asInterfaceInstance asInterfaceInstance}.
* This requirement may be tested via {@link #isWrapperInstance isWrapperInstance}.
* @param x any reference
* @return a method handle implementing the unique method
* @throws IllegalArgumentException if the reference x is not to a wrapper instance
*/
public static
MethodHandle wrapperInstanceTarget(Object x) {
return asWrapperInstance(x).getWrapperInstanceTarget();
}
/**
* Recovers the unique single-method interface type for which this wrapper instance was created.
* The object {@code x} must have been produced by a call to {@link #asInterfaceInstance asInterfaceInstance}.
* This requirement may be tested via {@link #isWrapperInstance isWrapperInstance}.
* @param x any reference
* @return the single-method interface type for which the wrapper was created
* @throws IllegalArgumentException if the reference x is not to a wrapper instance
*/
public static
Class<?> wrapperInstanceType(Object x) {
return asWrapperInstance(x).getWrapperInstanceType();
}
private static
boolean isObjectMethod(Method m) {
switch (m.getName()) {
case "toString":
return (m.getReturnType() == String.class
&& m.getParameterTypes().length == 0);
case "hashCode":
return (m.getReturnType() == int.class
&& m.getParameterTypes().length == 0);
case "equals":
return (m.getReturnType() == boolean.class
&& m.getParameterTypes().length == 1
&& m.getParameterTypes()[0] == Object.class);
}
return false;
}
private static
Object callObjectMethod(Object self, Method m, Object[] args) {
assert(isObjectMethod(m)) : m;
switch (m.getName()) {
case "toString":
return self.getClass().getName() + "@" + Integer.toHexString(self.hashCode());
case "hashCode":
return System.identityHashCode(self);
case "equals":
return (self == args[0]);
}
return null;
}
private static
Method getSingleMethod(Class<?> intfc) {
if (!intfc.isInterface()) return null;
Method sm = null;
for (Method m : intfc.getMethods()) {
int mod = m.getModifiers();
if (Modifier.isAbstract(mod)) {
if (sm != null && !isObjectMethod(sm))
return null; // too many abstract methods
sm = m;
}
}
return sm;
}
}

View File

@ -25,6 +25,9 @@
package java.lang.invoke; package java.lang.invoke;
import java.security.AccessController;
import java.security.PrivilegedAction;
/** /**
* This class consists exclusively of static names internal to the * This class consists exclusively of static names internal to the
* method handle implementation. * method handle implementation.
@ -35,6 +38,18 @@ package java.lang.invoke;
private MethodHandleStatics() { } // do not instantiate private MethodHandleStatics() { } // do not instantiate
static final boolean DEBUG_METHOD_HANDLE_NAMES;
static {
final Object[] values = { false };
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
values[0] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DEBUG_NAMES");
return null;
}
});
DEBUG_METHOD_HANDLE_NAMES = (Boolean) values[0];
}
/*non-public*/ static String getNameString(MethodHandle target, MethodType type) { /*non-public*/ static String getNameString(MethodHandle target, MethodType type) {
if (type == null) if (type == null)
type = target.type(); type = target.type();

File diff suppressed because it is too large Load Diff

View File

@ -163,7 +163,13 @@ class MethodType implements java.io.Serializable {
public static public static
MethodType methodType(Class<?> rtype, List<Class<?>> ptypes) { MethodType methodType(Class<?> rtype, List<Class<?>> ptypes) {
boolean notrust = false; // random List impl. could return evil ptypes array boolean notrust = false; // random List impl. could return evil ptypes array
return makeImpl(rtype, ptypes.toArray(NO_PTYPES), notrust); return makeImpl(rtype, listToArray(ptypes), notrust);
}
private static Class<?>[] listToArray(List<Class<?>> ptypes) {
// sanity check the size before the toArray call, since size might be huge
checkSlotCount(ptypes.size());
return ptypes.toArray(NO_PTYPES);
} }
/** /**
@ -228,7 +234,7 @@ class MethodType implements java.io.Serializable {
*/ */
/*trusted*/ static /*trusted*/ static
MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) { MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
if (ptypes == null || ptypes.length == 0) { if (ptypes.length == 0) {
ptypes = NO_PTYPES; trusted = true; ptypes = NO_PTYPES; trusted = true;
} }
MethodType mt1 = new MethodType(rtype, ptypes); MethodType mt1 = new MethodType(rtype, ptypes);
@ -267,7 +273,7 @@ class MethodType implements java.io.Serializable {
* @param objectArgCount number of parameters (excluding the final array parameter if any) * @param objectArgCount number of parameters (excluding the final array parameter if any)
* @param finalArray whether there will be a trailing array parameter, of type {@code Object[]} * @param finalArray whether there will be a trailing array parameter, of type {@code Object[]}
* @return a generally applicable method type, for all calls of the given fixed argument count and a collected array of further arguments * @return a generally applicable method type, for all calls of the given fixed argument count and a collected array of further arguments
* @throws IllegalArgumentException if {@code objectArgCount} is negative or greater than 255 (or 254, if {@code finalArray}) * @throws IllegalArgumentException if {@code objectArgCount} is negative or greater than 255 (or 254, if {@code finalArray} is true)
* @see #genericMethodType(int) * @see #genericMethodType(int)
*/ */
public static public static
@ -372,7 +378,7 @@ class MethodType implements java.io.Serializable {
* @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
*/ */
public MethodType insertParameterTypes(int num, List<Class<?>> ptypesToInsert) { public MethodType insertParameterTypes(int num, List<Class<?>> ptypesToInsert) {
return insertParameterTypes(num, ptypesToInsert.toArray(NO_PTYPES)); return insertParameterTypes(num, listToArray(ptypesToInsert));
} }
/** /**
@ -449,7 +455,8 @@ class MethodType implements java.io.Serializable {
/** /**
* Reports if this type contains a wrapper argument or return value. * Reports if this type contains a wrapper argument or return value.
* Wrappers are types which box primitive values, such as {@link Integer}. * Wrappers are types which box primitive values, such as {@link Integer}.
* The reference type {@code java.lang.Void} counts as a wrapper. * The reference type {@code java.lang.Void} counts as a wrapper,
* if it occurs as a return type.
* @return true if any of the types are wrappers * @return true if any of the types are wrappers
*/ */
public boolean hasWrappers() { public boolean hasWrappers() {
@ -641,14 +648,57 @@ class MethodType implements java.io.Serializable {
} }
return true; return true;
} }
private static boolean canConvert(Class<?> src, Class<?> dst) { /*non-public*/
if (src == dst || dst == void.class) return true; static boolean canConvert(Class<?> src, Class<?> dst) {
if (src.isPrimitive() && dst.isPrimitive()) { // short-circuit a few cases:
if (!Wrapper.forPrimitiveType(dst) if (src == dst || dst == Object.class) return true;
.isConvertibleFrom(Wrapper.forPrimitiveType(src))) // the remainder of this logic is documented in MethodHandle.asType
if (src.isPrimitive()) {
// can force void to an explicit null, a la reflect.Method.invoke
// can also force void to a primitive zero, by analogy
if (src == void.class) return true; //or !dst.isPrimitive()?
Wrapper sw = Wrapper.forPrimitiveType(src);
if (dst.isPrimitive()) {
// P->P must widen
return Wrapper.forPrimitiveType(dst).isConvertibleFrom(sw);
} else {
// P->R must box and widen
return dst.isAssignableFrom(sw.wrapperType());
}
} else if (dst.isPrimitive()) {
// any value can be dropped
if (dst == void.class) return true;
Wrapper dw = Wrapper.forPrimitiveType(dst);
// R->P must be able to unbox (from a dynamically chosen type) and widen
// For example:
// Byte/Number/Comparable/Object -> dw:Byte -> byte.
// Character/Comparable/Object -> dw:Character -> char
// Boolean/Comparable/Object -> dw:Boolean -> boolean
// This means that dw must be cast-compatible with src.
if (src.isAssignableFrom(dw.wrapperType())) {
return true;
}
// The above does not work if the source reference is strongly typed
// to a wrapper whose primitive must be widened. For example:
// Byte -> unbox:byte -> short/int/long/float/double
// Character -> unbox:char -> int/long/float/double
if (Wrapper.isWrapperType(src) &&
dw.isConvertibleFrom(Wrapper.forWrapperType(src))) {
// can unbox from src and then widen to dst
return true;
}
// We have already covered cases which arise due to runtime unboxing
// of a reference type which covers several wrapper types:
// Object -> cast:Integer -> unbox:int -> long/float/double
// Serializable -> cast:Byte -> unbox:byte -> byte/short/int/long/float/double
// An marginal case is Number -> dw:Character -> char, which would be OK if there were a
// subclass of Number which wraps a value that can convert to char.
// Since there is none, we don't need an extra check here to cover char or boolean.
return false; return false;
} else {
// R->R always works, since null is always valid dynamically
return true;
} }
return true;
} }
/// Queries which have to do with the bytecode architecture /// Queries which have to do with the bytecode architecture
@ -733,15 +783,21 @@ class MethodType implements java.io.Serializable {
* @param descriptor a bytecode-level type descriptor string "(T...)T" * @param descriptor a bytecode-level type descriptor string "(T...)T"
* @param loader the class loader in which to look up the types * @param loader the class loader in which to look up the types
* @return a method type matching the bytecode-level type descriptor * @return a method type matching the bytecode-level type descriptor
* @throws NullPointerException if the string is null
* @throws IllegalArgumentException if the string is not well-formed * @throws IllegalArgumentException if the string is not well-formed
* @throws TypeNotPresentException if a named type cannot be found * @throws TypeNotPresentException if a named type cannot be found
*/ */
public static MethodType fromMethodDescriptorString(String descriptor, ClassLoader loader) public static MethodType fromMethodDescriptorString(String descriptor, ClassLoader loader)
throws IllegalArgumentException, TypeNotPresentException throws IllegalArgumentException, TypeNotPresentException
{ {
if (!descriptor.startsWith("(") || // also generates NPE if needed
descriptor.indexOf(')') < 0 ||
descriptor.indexOf('.') >= 0)
throw new IllegalArgumentException("not a method descriptor: "+descriptor);
List<Class<?>> types = BytecodeDescriptor.parseMethod(descriptor, loader); List<Class<?>> types = BytecodeDescriptor.parseMethod(descriptor, loader);
Class<?> rtype = types.remove(types.size() - 1); Class<?> rtype = types.remove(types.size() - 1);
Class<?>[] ptypes = types.toArray(NO_PTYPES); checkSlotCount(types.size());
Class<?>[] ptypes = listToArray(types);
return makeImpl(rtype, ptypes, true); return makeImpl(rtype, ptypes, true);
} }

View File

@ -448,6 +448,8 @@ class MethodTypeForm {
Class<?>[] cs = null; Class<?>[] cs = null;
for (int imax = ts.length, i = 0; i < imax; i++) { for (int imax = ts.length, i = 0; i < imax; i++) {
Class<?> c = canonicalize(ts[i], how); Class<?> c = canonicalize(ts[i], how);
if (c == void.class)
c = null; // a Void parameter was unwrapped to void; ignore
if (c != null) { if (c != null) {
if (cs == null) if (cs == null)
cs = ts.clone(); cs = ts.clone();

View File

@ -37,12 +37,13 @@ import java.util.concurrent.atomic.AtomicInteger;
* <p> * <p>
* Here is an example of a mutable call site which introduces a * Here is an example of a mutable call site which introduces a
* state variable into a method handle chain. * state variable into a method handle chain.
* <!-- JavaDocExamplesTest.testMutableCallSite -->
* <blockquote><pre> * <blockquote><pre>
MutableCallSite name = new MutableCallSite(MethodType.methodType(String.class)); MutableCallSite name = new MutableCallSite(MethodType.methodType(String.class));
MethodHandle MH_name = name.dynamicInvoker(); MethodHandle MH_name = name.dynamicInvoker();
MethodType MT_str2 = MethodType.methodType(String.class, String.class); MethodType MT_str1 = MethodType.methodType(String.class);
MethodHandle MH_upcase = MethodHandles.lookup() MethodHandle MH_upcase = MethodHandles.lookup()
.findVirtual(String.class, "toUpperCase", MT_str2); .findVirtual(String.class, "toUpperCase", MT_str1);
MethodHandle worker1 = MethodHandles.filterReturnValue(MH_name, MH_upcase); MethodHandle worker1 = MethodHandles.filterReturnValue(MH_name, MH_upcase);
name.setTarget(MethodHandles.constant(String.class, "Rocky")); name.setTarget(MethodHandles.constant(String.class, "Rocky"));
assertEquals("ROCKY", (String) worker1.invokeExact()); assertEquals("ROCKY", (String) worker1.invokeExact());
@ -53,8 +54,10 @@ assertEquals("FRED", (String) worker1.invokeExact());
* <p> * <p>
* The same call site may be used in several places at once. * The same call site may be used in several places at once.
* <blockquote><pre> * <blockquote><pre>
MethodHandle MH_dear = MethodHandles.lookup() MethodType MT_str2 = MethodType.methodType(String.class, String.class);
.findVirtual(String.class, "concat", MT_str2).bindTo(", dear?"); MethodHandle MH_cat = lookup().findVirtual(String.class,
"concat", methodType(String.class, String.class));
MethodHandle MH_dear = MethodHandles.insertArguments(MH_cat, 1, ", dear?");
MethodHandle worker2 = MethodHandles.filterReturnValue(MH_name, MH_dear); MethodHandle worker2 = MethodHandles.filterReturnValue(MH_name, MH_dear);
assertEquals("Fred, dear?", (String) worker2.invokeExact()); assertEquals("Fred, dear?", (String) worker2.invokeExact());
name.setTarget(MethodHandles.constant(String.class, "Wilma")); name.setTarget(MethodHandles.constant(String.class, "Wilma"));

View File

@ -126,7 +126,7 @@ class SpreadGeneric {
return spreadGen; return spreadGen;
} }
public String toString() { String debugString() {
return getClass().getSimpleName()+targetType+"["+spreadCount+"]"; return getClass().getSimpleName()+targetType+"["+spreadCount+"]";
} }
@ -224,7 +224,7 @@ class SpreadGeneric {
protected final MethodHandle target; // (any**N) => R protected final MethodHandle target; // (any**N) => R
@Override @Override
public String toString() { String debugString() {
return addTypeString(target, this); return addTypeString(target, this);
} }

View File

@ -56,16 +56,17 @@ package java.lang.invoke;
* <p> * <p>
* Here is an example of a switch point in action: * Here is an example of a switch point in action:
* <blockquote><pre> * <blockquote><pre>
MethodType MT_str2 = MethodType.methodType(String.class, String.class);
MethodHandle MH_strcat = MethodHandles.lookup() MethodHandle MH_strcat = MethodHandles.lookup()
.findVirtual(String.class, "concat", MT_str2); .findVirtual(String.class, "concat", MethodType.methodType(String.class, String.class));
SwitchPoint spt = new SwitchPoint(); SwitchPoint spt = new SwitchPoint();
assert(!spt.hasBeenInvalidated());
// the following steps may be repeated to re-use the same switch point: // the following steps may be repeated to re-use the same switch point:
MethodHandle worker1 = strcat; MethodHandle worker1 = MH_strcat;
MethodHandle worker2 = MethodHandles.permuteArguments(strcat, MT_str2, 1, 0); MethodHandle worker2 = MethodHandles.permuteArguments(MH_strcat, MH_strcat.type(), 1, 0);
MethodHandle worker = spt.guardWithTest(worker1, worker2); MethodHandle worker = spt.guardWithTest(worker1, worker2);
assertEquals("method", (String) worker.invokeExact("met", "hod")); assertEquals("method", (String) worker.invokeExact("met", "hod"));
SwitchPoint.invalidateAll(new SwitchPoint[]{ spt }); SwitchPoint.invalidateAll(new SwitchPoint[]{ spt });
assert(spt.hasBeenInvalidated());
assertEquals("hodmet", (String) worker.invokeExact("met", "hod")); assertEquals("hodmet", (String) worker.invokeExact("met", "hod"));
* </pre></blockquote> * </pre></blockquote>
* <p style="font-size:smaller;"> * <p style="font-size:smaller;">
@ -124,6 +125,33 @@ public class SwitchPoint {
this.mcsInvoker = mcs.dynamicInvoker(); this.mcsInvoker = mcs.dynamicInvoker();
} }
/**
* Determines if this switch point has been invalidated yet.
*
* <p style="font-size:smaller;">
* <em>Discussion:</em>
* Because of the one-way nature of invalidation, once a switch point begins
* to return true for {@code hasBeenInvalidated},
* it will always do so in the future.
* On the other hand, a valid switch point visible to other threads may
* be invalidated at any moment, due to a request by another thread.
* <p style="font-size:smaller;">
* Since invalidation is a global and immediate operation,
* the execution of this query, on a valid switchpoint,
* must be internally sequenced with any
* other threads that could cause invalidation.
* This query may therefore be expensive.
* The recommended way to build a boolean-valued method handle
* which queries the invalidation state of a switch point {@code s} is
* to call {@code s.guardWithTest} on
* {@link MethodHandles#constant constant} true and false method handles.
*
* @return true if this switch point has been invalidated
*/
public boolean hasBeenInvalidated() {
return (mcs.getTarget() != K_true);
}
/** /**
* Returns a method handle which always delegates either to the target or the fallback. * Returns a method handle which always delegates either to the target or the fallback.
* The method handle will delegate to the target exactly as long as the switch point is valid. * The method handle will delegate to the target exactly as long as the switch point is valid.
@ -136,6 +164,7 @@ public class SwitchPoint {
* @param fallback the method handle selected by the switch point after it is invalidated * @param fallback the method handle selected by the switch point after it is invalidated
* @return a combined method handle which always calls either the target or fallback * @return a combined method handle which always calls either the target or fallback
* @throws NullPointerException if either argument is null * @throws NullPointerException if either argument is null
* @throws IllegalArgumentException if the two method types do not match
* @see MethodHandles#guardWithTest * @see MethodHandles#guardWithTest
*/ */
public MethodHandle guardWithTest(MethodHandle target, MethodHandle fallback) { public MethodHandle guardWithTest(MethodHandle target, MethodHandle fallback) {

View File

@ -258,7 +258,7 @@ class ToGeneric {
return toGen; return toGen;
} }
public String toString() { String debugString() {
return "ToGeneric"+entryType return "ToGeneric"+entryType
+(primsAtEndOrder!=null?"[reorder]":""); +(primsAtEndOrder!=null?"[reorder]":"");
} }
@ -340,7 +340,7 @@ class ToGeneric {
protected final MethodHandle convert; // Object -> R protected final MethodHandle convert; // Object -> R
@Override @Override
public String toString() { String debugString() {
return target == null ? "prototype:"+convert : addTypeString(target, this); return target == null ? "prototype:"+convert : addTypeString(target, this);
} }

View File

@ -28,7 +28,8 @@
* the Java core class libraries and virtual machine. * the Java core class libraries and virtual machine.
* *
* <p> * <p>
* Certain types in this package have special relations to dynamic * As described in the Java Virtual Machine Specification,
* certain types in this package have special relations to dynamic
* language support in the virtual machine: * language support in the virtual machine:
* <ul> * <ul>
* <li>The class {@link java.lang.invoke.MethodHandle MethodHandle} contains * <li>The class {@link java.lang.invoke.MethodHandle MethodHandle} contains
@ -42,177 +43,16 @@
* </li> * </li>
* </ul> * </ul>
* *
* <h2><a name="jvm_mods"></a>Corresponding JVM bytecode format changes</h2> * <h2><a name="jvm_mods"></a>Summary of relevant Java Virtual Machine changes</h2>
* <em>The following low-level information is presented here as a preview of * The following low-level information summarizes relevant parts of the
* changes being made to the Java Virtual Machine specification for JSR 292. * Java Virtual Machine specification. For full details, please see the
* This information will be incorporated in a future version of the JVM specification.</em> * current version of that specification.
* *
* <h3><a name="indyinsn"></a>{@code invokedynamic} instruction format</h3> * Each occurrence of an {@code invokedynamic} instruction is called a <em>dynamic call site</em>.
* In bytecode, an {@code invokedynamic} instruction is formatted as five bytes. * <h3><a name="indyinsn"></a>{@code invokedynamic} instructions</h3>
* The first byte is the opcode 186 (hexadecimal {@code BA}).
* The next two bytes are a constant pool index (in the same format as for the other {@code invoke} instructions).
* The final two bytes are reserved for future use and required to be zero.
* The constant pool reference of an {@code invokedynamic} instruction is to a entry
* with tag {@code CONSTANT_InvokeDynamic} (decimal 18). See below for its format.
* The entry specifies the following information:
* <ul>
* <li>a bootstrap method (a {@link java.lang.invoke.MethodHandle MethodHandle} constant)</li>
* <li>the dynamic invocation name (a UTF8 string)</li>
* <li>the argument and return types of the call (encoded as a type descriptor in a UTF8 string)</li>
* <li>optionally, a sequence of additional <em>static arguments</em> to the bootstrap method ({@code ldc}-type constants)</li>
* </ul>
* <p>
* Each instance of an {@code invokedynamic} instruction is called a <em>dynamic call site</em>.
* Multiple instances of an {@code invokedynamic} instruction can share a single
* {@code CONSTANT_InvokeDynamic} entry.
* In any case, distinct call sites always have distinct linkage state.
* <p>
* A dynamic call site is originally in an unlinked state. In this state, there is * A dynamic call site is originally in an unlinked state. In this state, there is
* no target method for the call site to invoke. * no target method for the call site to invoke.
* A dynamic call site is linked by means of a bootstrap method,
* as <a href="#bsm">described below</a>.
*
* <h3><a name="indycon"></a>constant pool entries for {@code invokedynamic} instructions</h3>
* If a constant pool entry has the tag {@code CONSTANT_InvokeDynamic} (decimal 18),
* it must contain exactly four more bytes after the tag.
* These bytes are interpreted as two 16-bit indexes, in the usual {@code u2} format.
* The first pair of bytes after the tag must be an index into a side table called the
* <em>bootstrap method table</em>, which is stored in the {@code BootstrapMethods}
* attribute as <a href="#bsmattr">described below</a>.
* The second pair of bytes must be an index to a {@code CONSTANT_NameAndType}.
* <p> * <p>
* The first index specifies a bootstrap method used by the associated dynamic call sites.
* The second index specifies the method name, argument types, and return type of the dynamic call site.
* The structure of such an entry is therefore analogous to a {@code CONSTANT_Methodref},
* except that the bootstrap method specifier reference replaces
* the {@code CONSTANT_Class} reference of a {@code CONSTANT_Methodref} entry.
*
* <h3><a name="mtcon"></a>constant pool entries for {@linkplain java.lang.invoke.MethodType method types}</h3>
* If a constant pool entry has the tag {@code CONSTANT_MethodType} (decimal 16),
* it must contain exactly two more bytes, which must be an index to a {@code CONSTANT_Utf8}
* entry which represents a method type descriptor.
* <p>
* The JVM will ensure that on first
* execution of an {@code ldc} instruction for this entry, a {@link java.lang.invoke.MethodType MethodType}
* will be created which represents the type descriptor.
* Any classes mentioned in the {@code MethodType} will be loaded if necessary,
* but not initialized.
* Access checking and error reporting is performed exactly as it is for
* references by {@code ldc} instructions to {@code CONSTANT_Class} constants.
*
* <h3><a name="mhcon"></a>constant pool entries for {@linkplain java.lang.invoke.MethodHandle method handles}</h3>
* If a constant pool entry has the tag {@code CONSTANT_MethodHandle} (decimal 15),
* it must contain exactly three more bytes. The first byte after the tag is a subtag
* value which must be in the range 1 through 9, and the last two must be an index to a
* {@code CONSTANT_Fieldref}, {@code CONSTANT_Methodref}, or
* {@code CONSTANT_InterfaceMethodref} entry which represents a field or method
* for which a method handle is to be created.
* Furthermore, the subtag value and the type of the constant index value
* must agree according to the table below.
* <p>
* The JVM will ensure that on first execution of an {@code ldc} instruction
* for this entry, a {@link java.lang.invoke.MethodHandle MethodHandle} will be created which represents
* the field or method reference, according to the specific mode implied by the subtag.
* <p>
* As with {@code CONSTANT_Class} and {@code CONSTANT_MethodType} constants,
* the {@code Class} or {@code MethodType} object which reifies the field or method's
* type is created. Any classes mentioned in this reification will be loaded if necessary,
* but not initialized, and access checking and error reporting performed as usual.
* <p>
* Unlike the reflective {@code Lookup} API, there are no security manager calls made
* when these constants are resolved.
* <p>
* The method handle itself will have a type and behavior determined by the subtag as follows:
* <code>
* <table border=1 cellpadding=5 summary="CONSTANT_MethodHandle subtypes">
* <tr><th>N</th><th>subtag name</th><th>member</th><th>MH type</th><th>bytecode behavior</th><th>lookup expression</th></tr>
* <tr><td>1</td><td>REF_getField</td><td>C.f:T</td><td>(C)T</td><td>getfield C.f:T</td>
* <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findGetter findGetter(C.class,"f",T.class)}</td></tr>
* <tr><td>2</td><td>REF_getStatic</td><td>C.f:T</td><td>(&nbsp;)T</td><td>getstatic C.f:T</td>
* <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findStaticGetter findStaticGetter(C.class,"f",T.class)}</td></tr>
* <tr><td>3</td><td>REF_putField</td><td>C.f:T</td><td>(C,T)void</td><td>putfield C.f:T</td>
* <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findSetter findSetter(C.class,"f",T.class)}</td></tr>
* <tr><td>4</td><td>REF_putStatic</td><td>C.f:T</td><td>(T)void</td><td>putstatic C.f:T</td>
* <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findStaticSetter findStaticSetter(C.class,"f",T.class)}</td></tr>
* <tr><td>5</td><td>REF_invokeVirtual</td><td>C.m(A*)T</td><td>(C,A*)T</td><td>invokevirtual C.m(A*)T</td>
* <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findVirtual findVirtual(C.class,"m",MT)}</td></tr>
* <tr><td>6</td><td>REF_invokeStatic</td><td>C.m(A*)T</td><td>(C,A*)T</td><td>invokestatic C.m(A*)T</td>
* <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findStatic findStatic(C.class,"m",MT)}</td></tr>
* <tr><td>7</td><td>REF_invokeSpecial</td><td>C.m(A*)T</td><td>(C,A*)T</td><td>invokespecial C.m(A*)T</td>
* <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findSpecial findSpecial(C.class,"m",MT,this.class)}</td></tr>
* <tr><td>8</td><td>REF_newInvokeSpecial</td><td>C.&lt;init&gt;(A*)void</td><td>(A*)C</td><td>new C; dup; invokespecial C.&lt;init&gt;(A*)void</td>
* <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findConstructor findConstructor(C.class,MT)}</td></tr>
* <tr><td>9</td><td>REF_invokeInterface</td><td>C.m(A*)T</td><td>(C,A*)T</td><td>invokeinterface C.m(A*)T</td>
* <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findVirtual findVirtual(C.class,"m",MT)}</td></tr>
* </table>
* </code>
* Here, the type {@code C} is taken from the {@code CONSTANT_Class} reference associated
* with the {@code CONSTANT_NameAndType} descriptor.
* The field name {@code f} or method name {@code m} is taken from the {@code CONSTANT_NameAndType}
* as is the result type {@code T} and (in the case of a method or constructor) the argument type sequence
* {@code A*}.
* <p>
* Each method handle constant has an equivalent instruction sequence called its <em>bytecode behavior</em>.
* In general, creating a method handle constant can be done in exactly the same circumstances that
* the JVM would successfully resolve the symbolic references in the bytecode behavior.
* Also, the type of a method handle constant is such that a valid {@code invokeExact} call
* on the method handle has exactly the same JVM stack effects as the <em>bytecode behavior</em>.
* Finally, calling a method handle constant on a valid set of arguments has exactly the same effect
* and returns the same result (if any) as the corresponding <em>bytecode behavior</em>.
* <p>
* Each method handle constant also has an equivalent reflective <em>lookup expression</em>,
* which is a query to a method in {@link java.lang.invoke.MethodHandles.Lookup}.
* In the example lookup method expression given in the table above, the name {@code MT}
* stands for a {@code MethodType} built from {@code T} and the sequence of argument types {@code A*}.
* (Note that the type {@code C} is not prepended to the query type {@code MT} even if the member is non-static.)
* In the case of {@code findSpecial}, the name {@code this.class} refers to the class containing
* the bytecodes.
* <p>
* The special name {@code <clinit>} is not allowed.
* The special name {@code <init>} is not allowed except for subtag 8 as shown.
* <p>
* The JVM verifier and linker apply the same access checks and restrictions for these references as for the hypothetical
* bytecode instructions specified in the last column of the table.
* A method handle constant will successfully resolve to a method handle if the symbolic references
* of the corresponding bytecode instruction(s) would also resolve successfully.
* Otherwise, an attempt to resolve the constant will throw equivalent linkage errors.
* In particular, method handles to
* private and protected members can be created in exactly those classes for which the corresponding
* normal accesses are legal.
* <p>
* A constant may refer to a method or constructor with the {@code varargs}
* bit (hexadecimal {@code 0x0080}) set in its modifier bitmask.
* The method handle constant produced for such a method behaves as if
* it were created by {@link java.lang.invoke.MethodHandle#asVarargsCollector asVarargsCollector}.
* In other words, the constant method handle will exhibit variable arity,
* when invoked via {@code MethodHandle.invoke}.
* On the other hand, its behavior with respect to {@code invokeExact} will be the same
* as if the {@code varargs} bit were not set.
* <p>
* Although the {@code CONSTANT_MethodHandle} and {@code CONSTANT_MethodType} constant types
* resolve class names, they do not force class initialization.
* Method handle constants for subtags {@code REF_getStatic}, {@code REF_putStatic}, and {@code REF_invokeStatic}
* may force class initialization on their first invocation, just like the corresponding bytecodes.
* <p>
* The rules of section 5.4.3 of
* <cite>The Java&trade; Virtual Machine Specification</cite>
* apply to the resolution of {@code CONSTANT_MethodType}, {@code CONSTANT_MethodHandle},
* and {@code CONSTANT_InvokeDynamic} constants,
* by the execution of {@code invokedynamic} and {@code ldc} instructions.
* (Roughly speaking, this means that every use of a constant pool entry
* must lead to the same outcome.
* If the resolution succeeds, the same object reference is produced
* by every subsequent execution of the same instruction.
* If the resolution of the constant causes an error to occur,
* the same error will be re-thrown on every subsequent attempt
* to use this particular constant.)
* <p>
* Constants created by the resolution of these constant pool types are not necessarily
* interned. Except for {@code CONSTANT_Class} and {@code CONSTANT_String} entries,
* two distinct constant pool entries might not resolve to the same reference
* even if they contain the same symbolic reference.
*
* <h2><a name="bsm"></a>Bootstrap Methods</h2>
* Before the JVM can execute a dynamic call site (an {@code invokedynamic} instruction), * Before the JVM can execute a dynamic call site (an {@code invokedynamic} instruction),
* the call site must first be <em>linked</em>. * the call site must first be <em>linked</em>.
* Linking is accomplished by calling a <em>bootstrap method</em> * Linking is accomplished by calling a <em>bootstrap method</em>
@ -234,15 +74,14 @@
* call site execution. * call site execution.
* Linkage does not trigger class initialization. * Linkage does not trigger class initialization.
* <p> * <p>
* Next, the bootstrap method call is started, with at least four values being stacked: * The bootstrap method is invoked on at least three values:
* <ul> * <ul>
* <li>a {@code MethodHandle}, the resolved bootstrap method itself </li>
* <li>a {@code MethodHandles.Lookup}, a lookup object on the <em>caller class</em> in which dynamic call site occurs </li> * <li>a {@code MethodHandles.Lookup}, a lookup object on the <em>caller class</em> in which dynamic call site occurs </li>
* <li>a {@code String}, the method name mentioned in the call site </li> * <li>a {@code String}, the method name mentioned in the call site </li>
* <li>a {@code MethodType}, the resolved type descriptor of the call </li> * <li>a {@code MethodType}, the resolved type descriptor of the call </li>
* <li>optionally, one or more <a href="#args">additional static arguments</a> </li> * <li>optionally, between 1 and 251 additional static arguments taken from the constant pool </li>
* </ul> * </ul>
* The method handle is then applied to the other values as if by * Invocation is as if by
* {@link java.lang.invoke.MethodHandle#invoke MethodHandle.invoke}. * {@link java.lang.invoke.MethodHandle#invoke MethodHandle.invoke}.
* The returned result must be a {@link java.lang.invoke.CallSite CallSite} (or a subclass). * The returned result must be a {@link java.lang.invoke.CallSite CallSite} (or a subclass).
* The type of the call site's target must be exactly equal to the type * The type of the call site's target must be exactly equal to the type
@ -250,38 +89,15 @@
* the bootstrap method. * the bootstrap method.
* The call site then becomes permanently linked to the dynamic call site. * The call site then becomes permanently linked to the dynamic call site.
* <p> * <p>
* As long as each bootstrap method can be correctly invoked * As documented in the JVM specification, all failures arising from
* by <code>MethodHandle.invoke</code>, its detailed type is arbitrary. * the linkage of a dynamic call site are reported
* For example, the first argument could be {@code Object} * by a {@link java.lang.BootstrapMethodError BootstrapMethodError},
* instead of {@code MethodHandles.Lookup}, and the return type
* could also be {@code Object} instead of {@code CallSite}.
* (Note that the types and number of the stacked arguments limit
* the legal kinds of bootstrap methods to appropriately typed
* static methods and constructors of {@code CallSite} subclasses.)
* <p>
* After resolution, the linkage process may fail in a variety of ways.
* All failures are reported by a {@link java.lang.BootstrapMethodError BootstrapMethodError},
* which is thrown as the abnormal termination of the dynamic call * which is thrown as the abnormal termination of the dynamic call
* site execution. * site execution.
* The following circumstances will cause this: * If this happens, the same error will the thrown for all subsequent
* <ul> * attempts to execute the dynamic call site.
* <li>the index to the bootstrap method specifier is out of range </li>
* <li>the bootstrap method cannot be resolved </li>
* <li>the {@code MethodType} to pass to the bootstrap method cannot be resolved </li>
* <li>a static argument to the bootstrap method cannot be resolved
* (i.e., a {@code CONSTANT_Class}, {@code CONSTANT_MethodType},
* or {@code CONSTANT_MethodHandle} argument cannot be linked) </li>
* <li>the bootstrap method has the wrong arity,
* causing {@code MethodHandle.invoke} to throw {@code WrongMethodTypeException} </li>
* <li>the bootstrap method has a wrong argument or return type </li>
* <li>the bootstrap method invocation completes abnormally </li>
* <li>the result from the bootstrap invocation is not a reference to
* an object of type {@link java.lang.invoke.CallSite CallSite} </li>
* <li>the target of the {@code CallSite} does not have a target of
* the expected {@code MethodType} </li>
* </ul>
* *
* <h3><a name="linktime"></a>timing of linkage</h3> * <h3>timing of linkage</h3>
* A dynamic call site is linked just before its first execution. * A dynamic call site is linked just before its first execution.
* The bootstrap method call implementing the linkage occurs within * The bootstrap method call implementing the linkage occurs within
* a thread that is attempting a first execution. * a thread that is attempting a first execution.
@ -306,7 +122,7 @@
* all threads. Any other bootstrap method calls are allowed to complete, but their * all threads. Any other bootstrap method calls are allowed to complete, but their
* results are ignored, and their dynamic call site invocations proceed with the originally * results are ignored, and their dynamic call site invocations proceed with the originally
* chosen target object. * chosen target object.
*
* <p style="font-size:smaller;"> * <p style="font-size:smaller;">
* <em>Discussion:</em> * <em>Discussion:</em>
* These rules do not enable the JVM to duplicate dynamic call sites, * These rules do not enable the JVM to duplicate dynamic call sites,
@ -315,64 +131,15 @@
* just before its first invocation. * just before its first invocation.
* There is no way to undo the effect of a completed bootstrap method call. * There is no way to undo the effect of a completed bootstrap method call.
* *
* <h3><a name="bsmattr">the {@code BootstrapMethods} attribute </h3> * <h3>types of bootstrap methods</h3>
* Each {@code CONSTANT_InvokeDynamic} entry contains an index which references * As long as each bootstrap method can be correctly invoked
* a bootstrap method specifier; all such specifiers are contained in a separate array. * by {@code MethodHandle.invoke}, its detailed type is arbitrary.
* This array is defined by a class attribute named {@code BootstrapMethods}. * For example, the first argument could be {@code Object}
* The body of this attribute consists of a sequence of byte pairs, all interpreted as * instead of {@code MethodHandles.Lookup}, and the return type
* as 16-bit counts or constant pool indexes, in the {@code u2} format. * could also be {@code Object} instead of {@code CallSite}.
* The attribute body starts with a count of bootstrap method specifiers, * (Note that the types and number of the stacked arguments limit
* which is immediately followed by the sequence of specifiers. * the legal kinds of bootstrap methods to appropriately typed
* <p> * static methods and constructors of {@code CallSite} subclasses.)
* Each bootstrap method specifier contains an index to a
* {@code CONSTANT_MethodHandle} constant, which is the bootstrap
* method itself.
* This is followed by a count, and then a sequence (perhaps empty) of
* indexes to <a href="#args">additional static arguments</a>
* for the bootstrap method.
* <p>
* During class loading, the verifier must check the structure of the
* {@code BootstrapMethods} attribute. In particular, each constant
* pool index must be of the correct type. A bootstrap method index
* must refer to a {@code CONSTANT_MethodHandle} (tag 15).
* Every other index must refer to a valid operand of an
* {@code ldc_w} or {@code ldc2_w} instruction (tag 3..8 or 15..16).
*
* <h3><a name="args">static arguments to the bootstrap method</h3>
* An {@code invokedynamic} instruction specifies at least three arguments
* to pass to its bootstrap method:
* The caller class (expressed as a {@link java.lang.invoke.MethodHandles.Lookup Lookup object},
* the name (extracted from the {@code CONSTANT_NameAndType} entry),
* and the type (also extracted from the {@code CONSTANT_NameAndType} entry).
* The {@code invokedynamic} instruction may specify additional metadata values
* to pass to its bootstrap method.
* Collectively, these values are called <em>static arguments</em> to the
* {@code invokedynamic} instruction, because they are used once at link
* time to determine the instruction's behavior on subsequent sets of
* <em>dynamic arguments</em>.
* <p>
* Static arguments are used to communicate application-specific meta-data
* to the bootstrap method.
* Drawn from the constant pool, they may include references to classes, method handles,
* strings, or numeric data that may be relevant to the task of linking that particular call site.
* <p>
* Static arguments are specified constant pool indexes stored in the {@code BootstrapMethods} attribute.
* Before the bootstrap method is invoked, each index is used to compute an {@code Object}
* reference to the indexed value in the constant pool.
* The valid constant pool entries are listed in this table:
* <code>
* <table border=1 cellpadding=5 summary="Static argument types">
* <tr><th>entry type</th><th>argument type</th><th>argument value</th></tr>
* <tr><td>CONSTANT_String</td><td><code>java.lang.String</code></td><td>the indexed string literal</td></tr>
* <tr><td>CONSTANT_Class</td><td><code>java.lang.Class</code></td><td>the indexed class, resolved</td></tr>
* <tr><td>CONSTANT_Integer</td><td><code>java.lang.Integer</code></td><td>the indexed int value</td></tr>
* <tr><td>CONSTANT_Long</td><td><code>java.lang.Long</code></td><td>the indexed long value</td></tr>
* <tr><td>CONSTANT_Float</td><td><code>java.lang.Float</code></td><td>the indexed float value</td></tr>
* <tr><td>CONSTANT_Double</td><td><code>java.lang.Double</code></td><td>the indexed double value</td></tr>
* <tr><td>CONSTANT_MethodHandle</td><td><code>java.lang.invoke.MethodHandle</code></td><td>the indexed method handle constant</td></tr>
* <tr><td>CONSTANT_MethodType</td><td><code>java.lang.invoke.MethodType</code></td><td>the indexed method type constant</td></tr>
* </table>
* </code>
* <p> * <p>
* If a given {@code invokedynamic} instruction specifies no static arguments, * If a given {@code invokedynamic} instruction specifies no static arguments,
* the instruction's bootstrap method will be invoked on three arguments, * the instruction's bootstrap method will be invoked on three arguments,
@ -380,7 +147,8 @@
* If the {@code invokedynamic} instruction specifies one or more static arguments, * If the {@code invokedynamic} instruction specifies one or more static arguments,
* those values will be passed as additional arguments to the method handle. * those values will be passed as additional arguments to the method handle.
* (Note that because there is a limit of 255 arguments to any method, * (Note that because there is a limit of 255 arguments to any method,
* at most 252 extra arguments can be supplied.) * at most 251 extra arguments can be supplied, since the bootstrap method
* handle itself and its first three arguments must also be stacked.)
* The bootstrap method will be invoked as if by either {@code MethodHandle.invoke} * The bootstrap method will be invoked as if by either {@code MethodHandle.invoke}
* or {@code invokeWithArguments}. (There is no way to tell the difference.) * or {@code invokeWithArguments}. (There is no way to tell the difference.)
* <p> * <p>
@ -390,12 +158,11 @@
* then some or all of the arguments specified here may be collected into a trailing array parameter. * then some or all of the arguments specified here may be collected into a trailing array parameter.
* (This is not a special rule, but rather a useful consequence of the interaction * (This is not a special rule, but rather a useful consequence of the interaction
* between {@code CONSTANT_MethodHandle} constants, the modifier bit for variable arity methods, * between {@code CONSTANT_MethodHandle} constants, the modifier bit for variable arity methods,
* and the {@code java.lang.invoke.MethodHandle#asVarargsCollector asVarargsCollector} transformation.) * and the {@link java.lang.invoke.MethodHandle#asVarargsCollector asVarargsCollector} transformation.)
* <p> * <p>
* Given these rules, here are examples of legal bootstrap method declarations, * Given these rules, here are examples of legal bootstrap method declarations,
* given various numbers {@code N} of extra arguments. * given various numbers {@code N} of extra arguments.
* The first rows (marked {@code *}) will work for any number of extra arguments. * The first rows (marked {@code *}) will work for any number of extra arguments.
* <code>
* <table border=1 cellpadding=5 summary="Static argument types"> * <table border=1 cellpadding=5 summary="Static argument types">
* <tr><th>N</th><th>sample bootstrap method</th></tr> * <tr><th>N</th><th>sample bootstrap method</th></tr>
* <tr><td>*</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, Object... args)</code></td></tr> * <tr><td>*</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, Object... args)</code></td></tr>
@ -408,7 +175,6 @@
* <tr><td>2</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, String... args)</code></td></tr> * <tr><td>2</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, String... args)</code></td></tr>
* <tr><td>2</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, String x, int y)</code></td></tr> * <tr><td>2</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, String x, int y)</code></td></tr>
* </table> * </table>
* </code>
* The last example assumes that the extra arguments are of type * The last example assumes that the extra arguments are of type
* {@code CONSTANT_String} and {@code CONSTANT_Integer}, respectively. * {@code CONSTANT_String} and {@code CONSTANT_Integer}, respectively.
* The second-to-last example assumes that all extra arguments are of type * The second-to-last example assumes that all extra arguments are of type
@ -431,34 +197,6 @@
* since each call site could be given its own unique bootstrap method. * since each call site could be given its own unique bootstrap method.
* Such a practice is likely to produce large class files and constant pools. * Such a practice is likely to produce large class files and constant pools.
* *
* <h2><a name="structs"></a>Structure Summary</h2>
* <blockquote><pre>// summary of constant and attribute structures
struct CONSTANT_MethodHandle_info {
u1 tag = 15;
u1 reference_kind; // 1..8 (one of REF_invokeVirtual, etc.)
u2 reference_index; // index to CONSTANT_Fieldref or *Methodref
}
struct CONSTANT_MethodType_info {
u1 tag = 16;
u2 descriptor_index; // index to CONSTANT_Utf8, as in NameAndType
}
struct CONSTANT_InvokeDynamic_info {
u1 tag = 18;
u2 bootstrap_method_attr_index; // index into BootstrapMethods_attr
u2 name_and_type_index; // index to CONSTANT_NameAndType, as in Methodref
}
struct BootstrapMethods_attr {
u2 name; // CONSTANT_Utf8 = "BootstrapMethods"
u4 size;
u2 bootstrap_method_count;
struct bootstrap_method_specifier {
u2 bootstrap_method_ref; // index to CONSTANT_MethodHandle
u2 bootstrap_argument_count;
u2 bootstrap_arguments[bootstrap_argument_count]; // constant pool indexes
} bootstrap_methods[bootstrap_method_count];
}
* </pre></blockquote>
*
* @author John Rose, JSR 292 EG * @author John Rose, JSR 292 EG
* @since 1.7 * @since 1.7
*/ */

View File

@ -1013,6 +1013,12 @@ class InetAddress implements java.io.Serializable {
return InetAddress.getAllByName(host)[0]; return InetAddress.getAllByName(host)[0];
} }
// called from deployment cache manager
private static InetAddress getByName(String host, InetAddress reqAddr)
throws UnknownHostException {
return InetAddress.getAllByName(host, reqAddr)[0];
}
/** /**
* Given the name of a host, returns an array of its IP addresses, * Given the name of a host, returns an array of its IP addresses,
* based on the configured name service on the system. * based on the configured name service on the system.
@ -1054,6 +1060,11 @@ class InetAddress implements java.io.Serializable {
*/ */
public static InetAddress[] getAllByName(String host) public static InetAddress[] getAllByName(String host)
throws UnknownHostException { throws UnknownHostException {
return getAllByName(host, null);
}
private static InetAddress[] getAllByName(String host, InetAddress reqAddr)
throws UnknownHostException {
if (host == null || host.length() == 0) { if (host == null || host.length() == 0) {
InetAddress[] ret = new InetAddress[1]; InetAddress[] ret = new InetAddress[1];
@ -1113,7 +1124,7 @@ class InetAddress implements java.io.Serializable {
// We were expecting an IPv6 Litteral, but got something else // We were expecting an IPv6 Litteral, but got something else
throw new UnknownHostException("["+host+"]"); throw new UnknownHostException("["+host+"]");
} }
return getAllByName0(host); return getAllByName0(host, reqAddr, true);
} }
/** /**
@ -1174,6 +1185,12 @@ class InetAddress implements java.io.Serializable {
*/ */
static InetAddress[] getAllByName0 (String host, boolean check) static InetAddress[] getAllByName0 (String host, boolean check)
throws UnknownHostException { throws UnknownHostException {
return getAllByName0 (host, null, check);
}
private static InetAddress[] getAllByName0 (String host, InetAddress reqAddr, boolean check)
throws UnknownHostException {
/* If it gets here it is presumed to be a hostname */ /* If it gets here it is presumed to be a hostname */
/* Cache.get can return: null, unknownAddress, or InetAddress[] */ /* Cache.get can return: null, unknownAddress, or InetAddress[] */
@ -1191,7 +1208,7 @@ class InetAddress implements java.io.Serializable {
/* If no entry in cache, then do the host lookup */ /* If no entry in cache, then do the host lookup */
if (addresses == null) { if (addresses == null) {
addresses = getAddressesFromNameService(host); addresses = getAddressesFromNameService(host, reqAddr);
} }
if (addresses == unknown_array) if (addresses == unknown_array)
@ -1200,7 +1217,7 @@ class InetAddress implements java.io.Serializable {
return addresses.clone(); return addresses.clone();
} }
private static InetAddress[] getAddressesFromNameService(String host) private static InetAddress[] getAddressesFromNameService(String host, InetAddress reqAddr)
throws UnknownHostException throws UnknownHostException
{ {
InetAddress[] addresses = null; InetAddress[] addresses = null;
@ -1256,10 +1273,32 @@ class InetAddress implements java.io.Serializable {
} }
} }
// Cache the addresses. // More to do?
if (reqAddr != null && addresses.length > 1 && !addresses[0].equals(reqAddr)) {
// Find it?
int i = 1;
for (; i < addresses.length; i++) {
if (addresses[i].equals(reqAddr)) {
break;
}
}
// Rotate
if (i < addresses.length) {
InetAddress tmp, tmp2 = reqAddr;
for (int j = 0; j < i; j++) {
tmp = addresses[j];
addresses[j] = tmp2;
tmp2 = tmp;
}
addresses[i] = tmp2;
}
}
// Cache the address.
cacheAddresses(host, addresses, success); cacheAddresses(host, addresses, success);
if (!success && ex != null) if (!success && ex != null)
throw ex; throw ex;
} finally { } finally {
// Delete host from the lookupTable and notify // Delete host from the lookupTable and notify
// all threads waiting on the lookupTable monitor. // all threads waiting on the lookupTable monitor.
@ -1393,7 +1432,7 @@ class InetAddress implements java.io.Serializable {
InetAddress[] localAddrs; InetAddress[] localAddrs;
try { try {
localAddrs = localAddrs =
InetAddress.getAddressesFromNameService(local); InetAddress.getAddressesFromNameService(local, null);
} catch (UnknownHostException uhe) { } catch (UnknownHostException uhe) {
// Rethrow with a more informative error message. // Rethrow with a more informative error message.
UnknownHostException uhe2 = UnknownHostException uhe2 =

View File

@ -547,13 +547,8 @@ public final class NetworkInterface {
if (displayName != null) { if (displayName != null) {
result += " (" + displayName + ")"; result += " (" + displayName + ")";
} }
result += " index: "+index+" addresses:\n";
for (Enumeration e = getInetAddresses(); e.hasMoreElements(); ) {
InetAddress addr = (InetAddress)e.nextElement();
result += addr+";\n";
}
return result; return result;
} }
private static native void init();
private static native void init();
} }

View File

@ -127,11 +127,12 @@ class Socket implements java.io.Closeable {
} }
if (security != null) { if (security != null) {
if (epoint.isUnresolved()) if (epoint.isUnresolved())
security.checkConnect(epoint.getHostName(), epoint = new InetSocketAddress(epoint.getHostName(), epoint.getPort());
epoint.getPort()); if (epoint.isUnresolved())
security.checkConnect(epoint.getHostName(), epoint.getPort());
else else
security.checkConnect(epoint.getAddress().getHostAddress(), security.checkConnect(epoint.getAddress().getHostAddress(),
epoint.getPort()); epoint.getPort());
} }
impl = new SocksSocketImpl(p); impl = new SocksSocketImpl(p);
impl.setSocket(this); impl.setSocket(this);

View File

@ -40,7 +40,9 @@ import java.io.ObjectOutputStream;
import java.io.ObjectInputStream; import java.io.ObjectInputStream;
import java.io.IOException; import java.io.IOException;
import sun.net.util.IPAddressUtil; import sun.net.util.IPAddressUtil;
import sun.net.RegisteredDomain;
import sun.security.util.SecurityConstants; import sun.security.util.SecurityConstants;
import sun.security.util.Debug;
/** /**
@ -211,13 +213,32 @@ implements java.io.Serializable
// port range on host // port range on host
private transient int[] portrange; private transient int[] portrange;
// true if the trustProxy system property is set private transient boolean defaultDeny = false;
private static boolean trustProxy;
// true if this SocketPermission represents a hostname
// that failed our reverse mapping heuristic test
private transient boolean untrusted;
private transient boolean trusted;
// true if the sun.net.trustNameService system property is set
private static boolean trustNameService;
private static Debug debug = null;
private static boolean debugInit = false;
static { static {
Boolean tmp = java.security.AccessController.doPrivileged( Boolean tmp = java.security.AccessController.doPrivileged(
new sun.security.action.GetBooleanAction("trustProxy")); new sun.security.action.GetBooleanAction("sun.net.trustNameService"));
trustProxy = tmp.booleanValue(); trustNameService = tmp.booleanValue();
}
private static synchronized Debug getDebug()
{
if (!debugInit) {
debug = Debug.getInstance("access");
debugInit = true;
}
return debug;
} }
/** /**
@ -263,6 +284,10 @@ implements java.io.Serializable
init(getName(), mask); init(getName(), mask);
} }
private void setDeny() {
defaultDeny = true;
}
private static String getHost(String host) private static String getHost(String host)
{ {
if (host.equals("")) { if (host.equals("")) {
@ -560,6 +585,37 @@ implements java.io.Serializable
return mask; return mask;
} }
private boolean isUntrusted()
throws UnknownHostException
{
if (trusted) return false;
if (invalid || untrusted) return true;
try {
if (!trustNameService && (defaultDeny ||
sun.net.www.URLConnection.isProxiedHost(hostname))) {
if (this.cname == null) {
this.getCanonName();
}
if (!match(cname, hostname)) {
// Last chance
if (!authorized(hostname, addresses[0].getAddress())) {
untrusted = true;
Debug debug = getDebug();
if (debug != null && Debug.isOn("failure")) {
debug.println("socket access restriction: proxied host " + "(" + addresses[0] + ")" + " does not match " + cname + " from reverse lookup");
}
return true;
}
}
trusted = true;
}
} catch (UnknownHostException uhe) {
invalid = true;
throw uhe;
}
return false;
}
/** /**
* attempt to get the fully qualified domain name * attempt to get the fully qualified domain name
* *
@ -567,7 +623,7 @@ implements java.io.Serializable
void getCanonName() void getCanonName()
throws UnknownHostException throws UnknownHostException
{ {
if (cname != null || invalid) return; if (cname != null || invalid || untrusted) return;
// attempt to get the canonical name // attempt to get the canonical name
@ -593,6 +649,96 @@ implements java.io.Serializable
} }
} }
private transient String cdomain, hdomain;
private boolean match(String cname, String hname) {
String a = cname.toLowerCase();
String b = hname.toLowerCase();
if (a.startsWith(b) &&
((a.length() == b.length()) || (a.charAt(b.length()) == '.')))
return true;
if (cdomain == null) {
cdomain = RegisteredDomain.getRegisteredDomain(a);
}
if (hdomain == null) {
hdomain = RegisteredDomain.getRegisteredDomain(b);
}
return cdomain.length() != 0 && hdomain.length() != 0
&& cdomain.equals(hdomain);
}
private boolean authorized(String cname, byte[] addr) {
if (addr.length == 4)
return authorizedIPv4(cname, addr);
else if (addr.length == 16)
return authorizedIPv6(cname, addr);
else
return false;
}
private boolean authorizedIPv4(String cname, byte[] addr) {
String authHost = "";
InetAddress auth;
try {
authHost = "auth." +
(addr[3] & 0xff) + "." + (addr[2] & 0xff) + "." +
(addr[1] & 0xff) + "." + (addr[0] & 0xff) +
".in-addr.arpa";
// Following check seems unnecessary
// auth = InetAddress.getAllByName0(authHost, false)[0];
authHost = hostname + '.' + authHost;
auth = InetAddress.getAllByName0(authHost, false)[0];
if (auth.equals(InetAddress.getByAddress(addr))) {
return true;
}
Debug debug = getDebug();
if (debug != null && Debug.isOn("failure")) {
debug.println("socket access restriction: IP address of " + auth + " != " + InetAddress.getByAddress(addr));
}
} catch (UnknownHostException uhe) {
Debug debug = getDebug();
if (debug != null && Debug.isOn("failure")) {
debug.println("socket access restriction: forward lookup failed for " + authHost);
}
}
return false;
}
private boolean authorizedIPv6(String cname, byte[] addr) {
String authHost = "";
InetAddress auth;
try {
StringBuffer sb = new StringBuffer(39);
for (int i = 15; i >= 0; i--) {
sb.append(Integer.toHexString(((addr[i]) & 0x0f)));
sb.append('.');
sb.append(Integer.toHexString(((addr[i] >> 4) & 0x0f)));
sb.append('.');
}
authHost = "auth." + sb.toString() + "IP6.ARPA";
//auth = InetAddress.getAllByName0(authHost, false)[0];
authHost = hostname + '.' + authHost;
auth = InetAddress.getAllByName0(authHost, false)[0];
if (auth.equals(InetAddress.getByAddress(addr)))
return true;
Debug debug = getDebug();
if (debug != null && Debug.isOn("failure")) {
debug.println("socket access restriction: IP address of " + auth + " != " + InetAddress.getByAddress(addr));
}
} catch (UnknownHostException uhe) {
Debug debug = getDebug();
if (debug != null && Debug.isOn("failure")) {
debug.println("socket access restriction: forward lookup failed for " + authHost);
}
}
return false;
}
/** /**
* get IP addresses. Sets invalid to true if we can't get them. * get IP addresses. Sets invalid to true if we can't get them.
* *
@ -720,12 +866,7 @@ implements java.io.Serializable
// return if either one of these NetPerm objects are invalid... // return if either one of these NetPerm objects are invalid...
if (this.invalid || that.invalid) { if (this.invalid || that.invalid) {
return (trustProxy ? inProxyWeTrust(that) : false); return compareHostnames(that);
}
if (this.getName().equalsIgnoreCase(that.getName())) {
return true;
} }
try { try {
@ -778,28 +919,29 @@ implements java.io.Serializable
that.getIP(); that.getIP();
} }
for (j = 0; j < this.addresses.length; j++) { if (!(that.init_with_ip && this.isUntrusted())) {
for (i=0; i < that.addresses.length; i++) { for (j = 0; j < this.addresses.length; j++) {
if (this.addresses[j].equals(that.addresses[i])) for (i=0; i < that.addresses.length; i++) {
return true; if (this.addresses[j].equals(that.addresses[i]))
return true;
}
} }
}
// XXX: if all else fails, compare hostnames? // XXX: if all else fails, compare hostnames?
// Do we really want this? // Do we really want this?
if (this.cname == null) { if (this.cname == null) {
this.getCanonName(); this.getCanonName();
} }
if (that.cname == null) { if (that.cname == null) {
that.getCanonName(); that.getCanonName();
} }
return (this.cname.equalsIgnoreCase(that.cname)); return (this.cname.equalsIgnoreCase(that.cname));
}
} catch (UnknownHostException uhe) { } catch (UnknownHostException uhe) {
if (trustProxy) return compareHostnames(that);
return inProxyWeTrust(that);
} }
// make sure the first thing that is done here is to return // make sure the first thing that is done here is to return
@ -808,9 +950,8 @@ implements java.io.Serializable
return false; return false;
} }
private boolean inProxyWeTrust(SocketPermission that) { private boolean compareHostnames(SocketPermission that) {
// if we trust the proxy, we see if the original names/IPs passed // we see if the original names/IPs passed in were equal.
// in were equal.
String thisHost = hostname; String thisHost = hostname;
String thatHost = that.hostname; String thatHost = that.hostname;
@ -819,8 +960,8 @@ implements java.io.Serializable
return false; return false;
else else
return thisHost.equalsIgnoreCase(thatHost); return thisHost.equalsIgnoreCase(thatHost);
} }
/** /**
* Checks two SocketPermission objects for equality. * Checks two SocketPermission objects for equality.
* <P> * <P>

View File

@ -460,15 +460,13 @@ public interface Path
/** /**
* Returns a URI to represent this path. * Returns a URI to represent this path.
* *
* <p> This method constructs a hierarchical {@link URI} that is absolute * <p> This method constructs an absolute {@link URI} with a {@link
* with a non-empty path component. Its {@link URI#getScheme() scheme} is * URI#getScheme() scheme} equal to the URI scheme that identifies the
* equal to the URI scheme that identifies the provider. The exact form of * provider. The exact form of the scheme specific part is highly provider
* the other URI components is highly provider dependent. In particular, it * dependent.
* is implementation dependent if its query, fragment, and authority
* components are defined or undefined.
* *
* <p> For the default provider the {@link URI#getPath() path} component * <p> In the case of the default provider, the URI is hierarchical with
* will represent the {@link #toAbsolutePath absolute} path; the query, * a {@link URI#getPath() path} component that is absolute. The query and
* fragment components are undefined. Whether the authority component is * fragment components are undefined. Whether the authority component is
* defined or not is implementation dependent. There is no guarantee that * defined or not is implementation dependent. There is no guarantee that
* the {@code URI} may be used to construct a {@link java.io.File java.io.File}. * the {@code URI} may be used to construct a {@link java.io.File java.io.File}.
@ -497,7 +495,7 @@ public interface Path
* A format for compound URIs is not defined in this release; such a scheme * A format for compound URIs is not defined in this release; such a scheme
* may be added in a future release. * may be added in a future release.
* *
* @return an absolute, hierarchical URI with a non-empty path component * @return the URI representing this path
* *
* @throws java.io.IOError * @throws java.io.IOError
* if an I/O error occurs obtaining the absolute path, or where a * if an I/O error occurs obtaining the absolute path, or where a

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2011, 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
@ -249,10 +249,10 @@ public final class SignedObject implements Serializable {
* a stream. * a stream.
*/ */
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();
s.defaultReadObject(); content = ((byte[])fields.get("content", null)).clone();
content = content.clone(); signature = ((byte[])fields.get("signature", null)).clone();
signature = signature.clone(); thealgorithm = (String)fields.get("thealgorithm", null);
} }
} }

View File

@ -79,7 +79,8 @@ public class BatchUpdateException extends SQLException {
*/ */
public BatchUpdateException( String reason, String SQLState, int vendorCode, public BatchUpdateException( String reason, String SQLState, int vendorCode,
int[] updateCounts ) { int[] updateCounts ) {
this(reason, SQLState, vendorCode, updateCounts, null); super(reason, SQLState, vendorCode);
this.updateCounts = (updateCounts == null) ? null : Arrays.copyOf(updateCounts, updateCounts.length);
} }
/** /**
@ -106,7 +107,7 @@ public class BatchUpdateException extends SQLException {
*/ */
public BatchUpdateException(String reason, String SQLState, public BatchUpdateException(String reason, String SQLState,
int[] updateCounts) { int[] updateCounts) {
this(reason, SQLState, 0, updateCounts, null); this(reason, SQLState, 0, updateCounts);
} }
/** /**
@ -132,7 +133,7 @@ public class BatchUpdateException extends SQLException {
* @since 1.2 * @since 1.2
*/ */
public BatchUpdateException(String reason, int[] updateCounts) { public BatchUpdateException(String reason, int[] updateCounts) {
this(reason, null, 0, updateCounts, null); this(reason, null, 0, updateCounts);
} }
/** /**
@ -155,7 +156,7 @@ public class BatchUpdateException extends SQLException {
* @since 1.2 * @since 1.2
*/ */
public BatchUpdateException(int[] updateCounts) { public BatchUpdateException(int[] updateCounts) {
this(null, null, 0, updateCounts, null); this(null, null, 0, updateCounts);
} }
/** /**
@ -170,7 +171,7 @@ public class BatchUpdateException extends SQLException {
* @since 1.2 * @since 1.2
*/ */
public BatchUpdateException() { public BatchUpdateException() {
this(null, null, 0, null, null); this(null, null, 0, null);
} }
/** /**

View File

@ -40,8 +40,7 @@ import javax.accessibility.*;
import sun.awt.AppContext; import sun.awt.AppContext;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.security.PrivilegedAction; import java.security.*;
import java.security.AccessController;
/** /**
* An implementation of the Icon interface that paints Icons * An implementation of the Icon interface that paints Icons
@ -81,32 +80,51 @@ public class ImageIcon implements Icon, Serializable, Accessible {
ImageObserver imageObserver; ImageObserver imageObserver;
String description = null; String description = null;
// Fields for twisted backward compatibility only. DO NOT USE.
protected final static Component component; protected final static Component component;
protected final static MediaTracker tracker; protected final static MediaTracker tracker;
static { static {
component = new Component() {}; component = AccessController.doPrivileged(new PrivilegedAction<Component>() {
AccessController.doPrivileged(new PrivilegedAction<Object>() { public Component run() {
public Object run() {
try { try {
final Component component = createNoPermsComponent();
// 6482575 - clear the appContext field so as not to leak it // 6482575 - clear the appContext field so as not to leak it
Field appContextField = Field appContextField =
Component.class.getDeclaredField("appContext");
Component.class.getDeclaredField("appContext");
appContextField.setAccessible(true); appContextField.setAccessible(true);
appContextField.set(component, null); appContextField.set(component, null);
}
catch (NoSuchFieldException e) { return component;
} catch (Throwable e) {
// We don't care about component.
// So don't prevent class initialisation.
e.printStackTrace(); e.printStackTrace();
return null;
} }
catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
} }
}); });
tracker = new MediaTracker(component); tracker = new MediaTracker(component);
} }
private static Component createNoPermsComponent() {
// 7020198 - set acc field to no permissions and no subject
// Note, will have appContext set.
return AccessController.doPrivileged(
new PrivilegedAction<Component>() {
public Component run() {
return new Component() {
};
}
},
new AccessControlContext(new ProtectionDomain[]{
new ProtectionDomain(null, null)
})
);
}
/** /**
* Id used in loading images from MediaTracker. * Id used in loading images from MediaTracker.
*/ */

View File

@ -588,6 +588,10 @@ public class NimbusLookAndFeel extends SynthLookAndFeel {
} }
private void addDefault(String key, Object value) { private void addDefault(String key, Object value) {
if (compiledDefaults == null) {
return;
}
String prefix = parsePrefix(key); String prefix = parsePrefix(key);
if (prefix != null) { if (prefix != null) {
Map<String, Object> keys = compiledDefaults.get(prefix); Map<String, Object> keys = compiledDefaults.get(prefix);

View File

@ -337,8 +337,7 @@ public class Utilities {
// x before x0, return. // x before x0, return.
return 0; return 0;
} }
int currX = x0; int nextX = x0;
int nextX = currX;
// s may be a shared segment, so it is copied prior to calling // s may be a shared segment, so it is copied prior to calling
// the tab expander // the tab expander
char[] txt = s.array; char[] txt = s.array;
@ -388,19 +387,45 @@ public class Utilities {
} else { } else {
nextX += metrics.charWidth(txt[i]); nextX += metrics.charWidth(txt[i]);
} }
if ((x >= currX) && (x < nextX)) { if (x < nextX) {
// found the hit position... return the appropriate side // found the hit position... return the appropriate side
int offset = ((round == false) || ((x - currX) < (nextX - x))) ? int offset;
(i - txtOffset) : (i + 1 - txtOffset);
// the length of the string measured as a whole may differ from // the length of the string measured as a whole may differ from
// the sum of individual character lengths, for example if // the sum of individual character lengths, for example if
// fractional metrics are enabled; and we must guard from this. // fractional metrics are enabled; and we must guard from this.
while (offset > 0 && metrics.charsWidth(txt, txtOffset, offset) > (x - x0)) { if (round) {
offset--; offset = i + 1 - txtOffset;
int width = metrics.charsWidth(txt, txtOffset, offset);
int span = x - x0;
if (span < width) {
while (offset > 0) {
int nextWidth = offset > 1 ? metrics.charsWidth(txt, txtOffset, offset - 1) : 0;
if (span >= nextWidth) {
if (span - nextWidth < width - span) {
offset--;
}
break;
}
width = nextWidth;
offset--;
}
}
} else {
offset = i - txtOffset;
while (offset > 0 && metrics.charsWidth(txt, txtOffset, offset) > (x - x0)) {
offset--;
}
} }
return offset; return offset;
} }
currX = nextX;
} }
// didn't find, return end offset // didn't find, return end offset

View File

@ -180,7 +180,6 @@ public class FileFontStrike extends PhysicalStrike {
pScalerContext = NullFontScaler.getNullScalerContext(); pScalerContext = NullFontScaler.getNullScalerContext();
} else { } else {
pScalerContext = fileFont.getScaler().createScalerContext(matrix, pScalerContext = fileFont.getScaler().createScalerContext(matrix,
fileFont instanceof TrueTypeFont,
desc.aaHint, desc.fmHint, desc.aaHint, desc.fmHint,
boldness, italic, disableHinting); boldness, italic, disableHinting);
} }

View File

@ -242,7 +242,6 @@ public abstract class FontScaler implements DisposerRecord {
freed when corresponding strike is being released. freed when corresponding strike is being released.
*/ */
abstract long createScalerContext(double[] matrix, abstract long createScalerContext(double[] matrix,
boolean fontType,
int aa, int fm, int aa, int fm,
float boldness, float italic, float boldness, float italic,
boolean disableHinting); boolean disableHinting);

View File

@ -210,12 +210,12 @@ class FreetypeFontScaler extends FontScaler {
return getUnitsPerEMNative(nativeScaler); return getUnitsPerEMNative(nativeScaler);
} }
long createScalerContext(double[] matrix, boolean fontType, long createScalerContext(double[] matrix,
int aa, int fm, float boldness, float italic, int aa, int fm, float boldness, float italic,
boolean disableHinting) { boolean disableHinting) {
if (nativeScaler != 0L) { if (nativeScaler != 0L) {
return createScalerContextNative(nativeScaler, matrix, return createScalerContextNative(nativeScaler, matrix,
fontType, aa, fm, boldness, italic); aa, fm, boldness, italic);
} }
return NullFontScaler.getNullScalerContext(); return NullFontScaler.getNullScalerContext();
} }
@ -254,7 +254,7 @@ class FreetypeFontScaler extends FontScaler {
private native long getUnitsPerEMNative(long pScaler); private native long getUnitsPerEMNative(long pScaler);
native long createScalerContextNative(long pScaler, double[] matrix, native long createScalerContextNative(long pScaler, double[] matrix,
boolean fontType, int aa, int fm, float boldness, float italic); int aa, int fm, float boldness, float italic);
/* Freetype scaler context does not contain any pointers that /* Freetype scaler context does not contain any pointers that
has to be invalidated if native scaler is bad */ has to be invalidated if native scaler is bad */

View File

@ -66,7 +66,7 @@ class NullFontScaler extends FontScaler {
long getLayoutTableCache() {return 0L;} long getLayoutTableCache() {return 0L;}
long createScalerContext(double[] matrix, boolean fontType, int aa, long createScalerContext(double[] matrix, int aa,
int fm, float boldness, float italic, boolean disableHinting) { int fm, float boldness, float italic, boolean disableHinting) {
return getNullScalerContext(); return getNullScalerContext();
} }

View File

@ -29,6 +29,8 @@ import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup; import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType; import java.lang.invoke.MethodType;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
@ -38,7 +40,17 @@ import java.util.List;
public class ValueConversions { public class ValueConversions {
private static final Class<?> THIS_CLASS = ValueConversions.class; private static final Class<?> THIS_CLASS = ValueConversions.class;
// Do not adjust this except for special platforms: // Do not adjust this except for special platforms:
private static final int MAX_ARITY = Integer.getInteger(THIS_CLASS.getName()+".MAX_ARITY", 255); private static final int MAX_ARITY;
static {
final Object[] values = { 255 };
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
values[0] = Integer.getInteger(THIS_CLASS.getName()+".MAX_ARITY", 255);
return null;
}
});
MAX_ARITY = (Integer) values[0];
}
private static final Lookup IMPL_LOOKUP = MethodHandles.lookup(); private static final Lookup IMPL_LOOKUP = MethodHandles.lookup();
@ -198,27 +210,30 @@ public class ValueConversions {
return unbox(Wrapper.forPrimitiveType(type), true, false); return unbox(Wrapper.forPrimitiveType(type), true, false);
} }
static private final Integer ZERO_INT = 0, ONE_INT = 1;
/// Primitive conversions /// Primitive conversions
public static Number primitiveConversion(Wrapper wrap, Object x, boolean cast) { public static Number primitiveConversion(Wrapper wrap, Object x, boolean cast) {
// Maybe merge this code with Wrapper.convert/cast. // Maybe merge this code with Wrapper.convert/cast.
Number res = null; Number res = null;
if (x == null) { if (x == null) {
if (!cast) return null; if (!cast) return null;
x = wrap.zero(); return ZERO_INT;
} }
if (x instanceof Number) { if (x instanceof Number) {
res = (Number) x; res = (Number) x;
} else if (x instanceof Boolean) { } else if (x instanceof Boolean) {
res = ((boolean)x ? 1 : 0); res = ((boolean)x ? ONE_INT : ZERO_INT);
} else if (x instanceof Character) { } else if (x instanceof Character) {
res = (int)(char)x; res = (int)(char)x;
} else { } else {
// this will fail with the required ClassCastException: // this will fail with the required ClassCastException:
res = (Number) x; res = (Number) x;
} }
if (!cast && !wrap.isConvertibleFrom(Wrapper.forWrapperType(x.getClass()))) Wrapper xwrap = Wrapper.findWrapperType(x.getClass());
if (xwrap == null || !cast && !wrap.isConvertibleFrom(xwrap))
// this will fail with the required ClassCastException: // this will fail with the required ClassCastException:
res = (Number) wrap.wrapperType().cast(x); return (Number) wrap.wrapperType().cast(x);
return res; return res;
} }

View File

@ -154,9 +154,10 @@ public class VerifyAccess {
* @return whether they are in the same package * @return whether they are in the same package
*/ */
public static boolean isSamePackage(Class<?> class1, Class<?> class2) { public static boolean isSamePackage(Class<?> class1, Class<?> class2) {
assert(!class1.isArray() && !class2.isArray());
if (class1 == class2) if (class1 == class2)
return true; return true;
if (!loadersAreRelated(class1.getClassLoader(), class2.getClassLoader())) if (!loadersAreRelated(class1.getClassLoader(), class2.getClassLoader(), false))
return false; return false;
String name1 = class1.getName(), name2 = class2.getName(); String name1 = class1.getName(), name2 = class2.getName();
int dot = name1.lastIndexOf('.'); int dot = name1.lastIndexOf('.');
@ -169,6 +170,16 @@ public class VerifyAccess {
return true; return true;
} }
/** Return the package name for this class.
*/
public static String getPackageName(Class<?> cls) {
assert(!cls.isArray());
String name = cls.getName();
int dot = name.lastIndexOf('.');
if (dot < 0) return "";
return name.substring(0, dot);
}
/** /**
* Test if two classes are defined as part of the same package member (top-level class). * Test if two classes are defined as part of the same package member (top-level class).
* If this is true, they can share private access with each other. * If this is true, they can share private access with each other.
@ -193,18 +204,33 @@ public class VerifyAccess {
return pkgmem; return pkgmem;
} }
private static boolean loadersAreRelated(ClassLoader loader1, ClassLoader loader2) { private static boolean loadersAreRelated(ClassLoader loader1, ClassLoader loader2,
if (loader1 == loader2 || loader1 == null || loader2 == null) { boolean loader1MustBeParent) {
if (loader1 == loader2 || loader1 == null
|| (loader2 == null && !loader1MustBeParent)) {
return true; return true;
} }
for (ClassLoader scan1 = loader1;
scan1 != null; scan1 = scan1.getParent()) {
if (scan1 == loader2) return true;
}
for (ClassLoader scan2 = loader2; for (ClassLoader scan2 = loader2;
scan2 != null; scan2 = scan2.getParent()) { scan2 != null; scan2 = scan2.getParent()) {
if (scan2 == loader1) return true; if (scan2 == loader1) return true;
} }
if (loader1MustBeParent) return false;
// see if loader2 is a parent of loader1:
for (ClassLoader scan1 = loader1;
scan1 != null; scan1 = scan1.getParent()) {
if (scan1 == loader2) return true;
}
return false; return false;
} }
/**
* Is the class loader of parentClass identical to, or an ancestor of,
* the class loader of childClass?
* @param parentClass
* @param childClass
* @return whether parentClass precedes or equals childClass in class loader order
*/
public static boolean classLoaderIsAncestor(Class<?> parentClass, Class<?> childClass) {
return loadersAreRelated(parentClass.getClassLoader(), childClass.getClassLoader(), true);
}
} }

View File

@ -135,7 +135,7 @@ public enum Wrapper {
* <li>any type converted to {@code void} (i.e., dropping a method call's value) * <li>any type converted to {@code void} (i.e., dropping a method call's value)
* <li>boxing conversion followed by widening reference conversion to {@code Object} * <li>boxing conversion followed by widening reference conversion to {@code Object}
* </ul> * </ul>
* These are the cases allowed by MethodHandle.asType and convertArguments. * These are the cases allowed by MethodHandle.asType.
*/ */
public boolean isConvertibleFrom(Wrapper source) { public boolean isConvertibleFrom(Wrapper source) {
if (this == source) return true; if (this == source) return true;
@ -258,7 +258,7 @@ public enum Wrapper {
} }
/** Return the wrapper that wraps values into the given wrapper type. /** Return the wrapper that wraps values into the given wrapper type.
* If it is {@code Object} or an interface, return {@code OBJECT}. * If it is {@code Object}, return {@code OBJECT}.
* Otherwise, it must be a wrapper type. * Otherwise, it must be a wrapper type.
* The type must not be a primitive type. * The type must not be a primitive type.
* @throws IllegalArgumentException for unexpected types * @throws IllegalArgumentException for unexpected types
@ -277,8 +277,6 @@ public enum Wrapper {
if (w != null && w.wrapperType == type) { if (w != null && w.wrapperType == type) {
return w; return w;
} }
if (type.isInterface())
return OBJECT;
return null; return null;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2010, 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

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2010, 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

View File

@ -509,6 +509,9 @@ public class DrawImage implements DrawImagePipe
* edges thus has to be h*2+2 in length * edges thus has to be h*2+2 in length
*/ */
int edges[] = new int[(dy2-dy1)*2+2]; int edges[] = new int[(dy2-dy1)*2+2];
// It is important that edges[0]=edges[1]=0 when we call
// Transform in case it must return early and we would
// not want to render anything on an error condition.
helper.Transform(tmpmaskblit, srcData, tmpData, helper.Transform(tmpmaskblit, srcData, tmpData,
AlphaComposite.Src, null, AlphaComposite.Src, null,
itx, interpType, itx, interpType,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2010 Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2010, 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

View File

@ -532,15 +532,11 @@ public class URLClassPath {
uc = url.openConnection(); uc = url.openConnection();
InputStream in = uc.getInputStream(); InputStream in = uc.getInputStream();
if (uc instanceof JarURLConnection) { if (uc instanceof JarURLConnection) {
/* JarURLConnection.getInputStream() returns a separate /* Need to remember the jar file so it can be closed
* instance on each call. So we have to close this here.
* The jar file cache will keep the file open.
* Also, need to remember the jar file so it can be closed
* in a hurry. * in a hurry.
*/ */
JarURLConnection juc = (JarURLConnection)uc; JarURLConnection juc = (JarURLConnection)uc;
jarfile = juc.getJarFile(); jarfile = juc.getJarFile();
in.close();
} }
} catch (Exception e) { } catch (Exception e) {
return null; return null;

View File

@ -0,0 +1,879 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute 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 sun.net;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/*
* The naming tables listed below were gathered from publicly available data such as
* the subdomain registration websites listed for each top-level domain by the Internet
* Assigned Numbers Authority and the website of the Internet Corporation for Assigned Names
* and Numbers as well as Wikipedia.
*/
public class RegisteredDomain {
// XX.AA
private static Set<String> top1Set = new HashSet<String>(Arrays.asList("asia", "biz", "cat", "coop",
"edu", "info", "gov", "jobs", "travel", "am", "aq", "ax", "cc", "cf", "cg", "ch", "cv", "cz",
"de", "dj", "dk", "fm", "fo", "ga", "gd", "gf", "gl", "gm", "gq", "gs", "gw", "hm",
"li", "lu", "md", "mh", "mil", "mobi", "mq", "ms", "ms", "ne", "nl", "nu", "si",
"sm", "sr", "su", "tc", "td", "tf", "tg", "tk", "tm", "tv", "va", "vg",
/* ae */ "xn--mgbaam7a8h", /* cn s */ "xn--fiqs8s", /* cn t */ "xn--fiqz9s",
/* eg */ "xn--wgbh1c", /* hk */ "xn--j6w193g", /* jo */ "xn--mgbayh7gpa",
/* lk */ "xn--fzc2c9e2c", /* ps */ "xn--ygbi2ammx", /* ru */ "xn--p1ai",
/* qa */ "xn--wgbl6a", /* sa */ "xn--mgberp4a5d4ar", /* sg */ "xn--yfro4i67o",
/* th */ "xn--o3cw4h", /* tn */ "xn--pgbs0dh", /* tw s */ "xn--kpry57d",
/* tw */ "xn--kprw13d", /* sg tamil */ "xn--clchc0ea0b2g2a9gcd"));
// common pattern: XX.AA or XX.GOV.AA
private static Set<String> top2Set = new HashSet<String>(Arrays.asList("as", "bf", "cd", "cx",
"ie", "lt", "mr", "tl"));
// common pattern: XX.AA or XX.COM.AA or XX.EDU.AA or XX.NET.AA or XX.ORG.AA or XX.GOV.AA
private static Set<String> top4Set = new HashSet<String>(Arrays.asList("af", "bm", "bs", "bt",
"bz", "dm", "ky", "lb", "lr", "mo", "sc", "sl", "ws"));
// AA or less than 3 other XX.BB.AA possible matches
private static Set<String> top3Set = new HashSet<String>(Arrays.asList("ad", "aw", "be", "bw",
"cl", "fi", "int", "io", "mc"));
// AA.UK exceptions
private static Set<String> ukSet = new HashSet<String>(Arrays.asList( "bl", "british-library",
"jet", "nhs", "nls", "parliament", "mod", "police"));
// AA.AR exceptions
private static Set<String> arSet = new HashSet<String>(Arrays.asList( "argentina", "educ",
"gobiernoelectronico", "nic", "promocion", "retina", "uba"));
// AA.OM exceptions
private static Set<String> omSet = new HashSet<String>(Arrays.asList("mediaphone", "nawrastelecom",
"nawras", "omanmobile", "omanpost", "omantel", "rakpetroleum", "siemens", "songfest",
"statecouncil", "shura", "peie", "omran", "omnic", "omanet", "oman", "muriya", "kom"));
// any XX.BB.AA
private static Set<String> top5Set = new HashSet<String>(Arrays.asList("au", "arpa", "bd", "bn", "ck",
"cy", "er", "et", "fj", "fk", "gt", "gu", "il", "jm", "ke", "kh", "kw",
"mm", "mt", "mz", "ni", "np", "nz", "pg", "sb", "sv", "tz", "uy", "ve", "ye",
"za", "zm", "zw"));
// XX.CC.BB.JP
private static Set<String> jpSet = new HashSet<String>(Arrays.asList("aichi", "akita", "aomori",
"chiba", "ehime", "fukui", "fukuoka", "fukushima", "gifu", "gunma", "hiroshima", "hokkaido",
"hyogo", "ibaraki", "ishikawa", "iwate", "kagawa", "kagoshima", "kanagawa", "kawasaki",
"kitakyushu", "kobe", "kochi", "kumamoto", "kyoto", "mie", "miyagi", "miyazaki", "nagano",
"nagasaki", "nagoya", "nara", "niigata", "oita", "okayama", "okinawa", "osaka", "saga",
"saitama", "sapporo", "sendai", "shiga", "shimane", "shizuoka", "tochigi", "tokushima",
"tokyo", "tottori", "toyama", "wakayama", "yamagata", "yamaguchi", "yamanashi", "yokohama"));
// CC.BB.JP exceptions
private static Set<String> jp2Set = new HashSet<String>(Arrays.asList("metro.tokyo.jp",
"pref.aichi.jp", "pref.akita.jp", "pref.aomori.jp", "pref.chiba.jp", "pref.ehime.jp",
"pref.fukui.jp", "pref.fukuoka.jp", "pref.fukushima.jp", "pref.gifu.jp", "pref.gunma.jp",
"pref.hiroshima.jp", "pref.hokkaido.jp", "pref.hyogo.jp", "pref.ibaraki.jp", "pref.ishikawa.jp",
"pref.iwate.jp", "pref.kagawa.jp", "pref.kagoshima.jp", "pref.kanagawa.jp", "pref.kochi.jp",
"pref.kumamoto.jp", "pref.kyoto.jp", "pref.mie.jp", "pref.miyagi.jp", "pref.miyazaki.jp",
"pref.nagano.jp", "pref.nagasaki.jp", "pref.nara.jp", "pref.niigata.jp", "pref.oita.jp",
"pref.okayama.jp", "pref.okinawa.jp", "pref.osaka.jp", "pref.saga.jp", "pref.saitama.jp",
"pref.shiga.jp", "pref.shimane.jp", "pref.shizuoka.jp", "pref.tochigi.jp", "pref.tokushima.jp",
"pref.tottori.jp", "pref.toyama.jp", "pref.wakayama.jp", "pref.yamagata.jp", "pref.yamaguchi.jp",
"pref.yamanashi.jp", "city.chiba.jp", "city.fukuoka.jp", "city.hamamatsu.jp", "city.hiroshima.jp", "city.kawasaki.jp",
"city.kitakyushu.jp", "city.kobe.jp", "city.kyoto.jp", "city.nagoya.jp", "city.niigata.jp",
"city.okayama.jp", "city.osaka.jp", "city.sagamihara.jp", "city.saitama.jp", "city.sapporo.jp", "city.sendai.jp",
"city.shizuoka.jp", "city.yokohama.jp"));
private static Set<String> usStateSet = new HashSet<String>(Arrays.asList("ak",
"al", "ar", "as", "az", "ca", "co", "ct", "dc", "de", "fl", "ga", "gu", "hi", "ia",
"id", "il", "in", "ks", "ky", "la", "ma", "md", "me", "mi", "mn", "mo", "ms", "mt",
"nc", "nd", "ne", "nh", "nj", "nm", "nv", "ny", "oh", "ok", "or", "pa", "pr", "ri",
"sc", "sd", "tn", "tx", "ut", "vi", "vt", "va", "wa", "wi", "wv", "wy"));
private static Set<String> usSubStateSet = new HashSet<String>(Arrays.asList("state",
"lib", "k12", "cc", "tec", "gen", "cog", "mus", "dst"));
private static Map<String,Set> topMap = new HashMap<String,Set>();
private static Map<String,Set> top3Map = new HashMap<String,Set>();
static {
/*
* XX.AA or XX.BB.AA
*/
topMap.put("ac", new HashSet<String>(Arrays.asList("com", "co", "edu", "gov", "net", "mil", "org")));
topMap.put("ae", new HashSet<String>(Arrays.asList("co", "net", "org", "sch", "ac", "gov", "mil")));
topMap.put("aero", new HashSet<String>(Arrays.asList("accident-investigation",
"accident-prevention", "aerobatic", "aeroclub", "aerodrome", "agents", "aircraft",
"airline", "airport", "air-surveillance", "airtraffic", "air-traffic-control",
"ambulance", "amusement", "association", "author", "ballooning", "broker", "caa",
"cargo", "catering", "certification", "championship", "charter", "civilaviation",
"club", "conference", "consultant", "consulting", "control", "council", "crew",
"design", "dgca", "educator", "emergency", "engine", "engineer", "entertainment",
"equipment", "exchange", "express", "federation", "flight", "freight", "fuel",
"gliding", "government", "groundhandling", "group", "hanggliding", "homebuilt",
"insurance", "journal", "journalist", "leasing", "logistics", "magazine",
"maintenance", "marketplace", "media", "microlight", "modelling", "navigation",
"parachuting", "paragliding", "passenger-association", "pilot", "press", "production",
"recreation", "repbody", "res", "research", "rotorcraft", "safety", "scientist",
"services", "show", "skydiving", "software", "student", "taxi", "trader", "trading",
"trainer", "union", "workinggroup", "works" )));
topMap.put( "ag", new HashSet<String>(Arrays.asList("com", "org", "net", "co", "nom")));
topMap.put( "ai", new HashSet<String>(Arrays.asList("off", "com", "net", "org")));
topMap.put( "al", new HashSet<String>(Arrays.asList("com", "edu", "gov", "mil", "net", "org")));
topMap.put( "an", new HashSet<String>(Arrays.asList("com")));
topMap.put( "ao", new HashSet<String>(Arrays.asList("ed", "gv", "og", "co", "pb", "it")));
topMap.put( "at", new HashSet<String>(Arrays.asList("ac", "co", "gv", "or", "biz", "info", "priv")));
topMap.put( "az", new HashSet<String>(Arrays.asList("com", "net", "int", "gov", "org", "edu", "info",
"pp", "mil", "name", "biz")));
topMap.put( "ba", new HashSet<String>(Arrays.asList("org", "net", "edu", "gov", "mil", "unbi",
"unmo", "unsa", "untz", "unze", "co", "com", "rs")));
topMap.put( "bb", new HashSet<String>(Arrays.asList("biz", "com", "edu", "gov", "info", "net", "org",
"store")));
topMap.put( "bg", new HashSet<String>(Arrays.asList("a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
"k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1",
"2", "3", "4", "5", "6", "7", "8", "9")));
topMap.put( "bh", new HashSet<String>(Arrays.asList("com", "info", "cc", "edu", "biz", "net",
"org", "gov")));
topMap.put( "bi", new HashSet<String>(Arrays.asList("co", "com", "edu", "gov", "info", "or", "org")));
topMap.put( "bj", new HashSet<String>(Arrays.asList("asso", "barreau", "com", "edu", "gouv", "gov", "mil")));
topMap.put( "bo", new HashSet<String>(Arrays.asList("com", "edu", "gov", "gob", "int", "org", "net",
"mil", "tv")));
topMap.put( "br", new HashSet<String>(Arrays.asList("adm", "adv", "agr", "am", "arq", "art", "ato",
"b", "bio", "blog", "bmd", "cim", "cng", "cnt", "com", "coop", "ecn", "edu", "emp", "eng",
"esp", "etc", "eti", "far", "flog", "fm", "fnd", "fot", "fst", "g12", "ggf", "gov",
"imb", "ind", "inf", "jor", "jus", "lel", "mat", "med", "mil", "mus", "net", "nom",
"not", "ntr", "odo", "org", "ppg", "pro", "psc", "psi", "qsl", "radio", "rec", "slg",
"srv", "taxi", "teo", "tmp", "trd", "tur", "tv", "vet", "vlog", "wiki", "zlg")));
topMap.put( "bw", new HashSet<String>(Arrays.asList("co", "gov", "org")));
topMap.put( "by", new HashSet<String>(Arrays.asList("gov", "mil", "com", "of")));
topMap.put( "ca", new HashSet<String>(Arrays.asList("ab", "bc", "mb", "nb", "nf",
"nl", "ns", "nt", "nu", "on", "pe", "qc", "sk", "yk", "gc")));
topMap.put( "ci", new HashSet<String>(Arrays.asList("org", "or", "com", "co", "edu",
"ed", "ac", "net", "go", "asso", "xn--aroport-bya", "int",
"presse", "md", "gouv")));
topMap.put( "com", new HashSet<String>(Arrays.asList("ad", "ar", "br", "cn", "de", "eu", "gb",
"gr", "hu", "jpn", "kr", "no", "qc", "ru", "sa", "se", "uk", "us", "uy", "za")));
topMap.put( "cm", new HashSet<String>(Arrays.asList("co", "com", "gov", "net")));
topMap.put( "cn", new HashSet<String>(Arrays.asList("ac", "com", "edu", "gov", "net",
"org", "mil", "xn--55qx5d", "xn--io0a7i",
"ah", "bj", "cq", "fj", "gd", "gs", "gz", "gx",
"ha", "hb", "he", "hi", "hl", "hn", "jl", "js", "jx", "ln", "nm", "nx", "qh",
"sc", "sd", "sh", "sn", "sx", "tj", "xj", "xz", "yn", "zj", "hk", "mo", "tw")));
topMap.put( "co", new HashSet<String>(Arrays.asList("arts", "com", "edu", "firm", "gov", "info",
"int", "mil", "net", "nom", "org", "rec", "web")));
topMap.put( "cr", new HashSet<String>(Arrays.asList("ac", "co", "ed", "fi", "go", "or", "sa")));
topMap.put( "cu", new HashSet<String>(Arrays.asList("com", "edu", "org", "net", "gov", "inf")));
topMap.put( "do", new HashSet<String>(Arrays.asList("com", "edu", "org", "net", "gov", "gob",
"web", "art", "sld", "mil")));
topMap.put( "dz", new HashSet<String>(Arrays.asList("com", "org", "net", "gov", "edu", "asso",
"pol", "art")));
topMap.put( "ec", new HashSet<String>(Arrays.asList("com", "info", "net", "fin", "k12", "med",
"pro", "org", "edu", "gov", "gob", "mil")));
topMap.put( "ee", new HashSet<String>(Arrays.asList("edu", "gov", "riik", "lib", "med", "com",
"pri", "aip", "org", "fie")));
topMap.put( "eg", new HashSet<String>(Arrays.asList("com", "edu", "eun", "gov", "mil", "name",
"net", "org", "sci")));
topMap.put( "es", new HashSet<String>(Arrays.asList("com", "nom", "org", "gob", "edu")));
topMap.put( "eu", new HashSet<String>(Arrays.asList("europa")));
topMap.put( "fr", new HashSet<String>(Arrays.asList("com", "asso", "nom", "prd", "presse",
"tm", "aeroport", "assedic", "avocat", "avoues", "cci", "chambagri",
"chirurgiens-dentistes", "experts-comptables", "geometre-expert", "gouv", "greta",
"huissier-justice", "medecin", "notaires", "pharmacien", "port", "veterinaire")));
topMap.put( "ge", new HashSet<String>(Arrays.asList("com", "edu", "gov", "org", "mil", "net", "pvt")));
topMap.put( "gg", new HashSet<String>(Arrays.asList("co", "org", "net", "sch", "gov")));
topMap.put( "gh", new HashSet<String>(Arrays.asList("com", "edu", "gov", "org", "mil")));
topMap.put( "gi", new HashSet<String>(Arrays.asList("com", "ltd", "gov", "mod", "edu", "org")));
topMap.put( "gn", new HashSet<String>(Arrays.asList("ac", "com", "edu", "gov", "org", "net")));
topMap.put( "gp", new HashSet<String>(Arrays.asList("com", "net", "mobi", "edu", "org", "asso")));
topMap.put( "gr", new HashSet<String>(Arrays.asList("com", "co", "net", "edu", "org", "gov",
"mil", "mod", "sch")));
topMap.put( "gy", new HashSet<String>(Arrays.asList("co", "com", "net", "org", "edu", "gov")));
topMap.put( "hk", new HashSet<String>(Arrays.asList("com", "edu", "gov", "idv", "net", "org",
/* com */ "xn--55qx5d", /* edu */ "xn--wcvs22d", /* gov */"xn--mxtq1m",
/* idv */ "xn--gmqw5a", /* net */ "xn--od0alg", /*org*/ "xn--uc0atv")));
topMap.put( /* hk */ "xn--j6w193g", new HashSet<String>(Arrays.asList(
/* com */ "xn--55qx5d", /* edu */ "xn--wcvs22d", /* gov */"xn--mxtq1m",
/* idv */ "xn--gmqw5a", /* net */ "xn--od0alg", /*org*/ "xn--uc0atv")));
topMap.put( "hn", new HashSet<String>(Arrays.asList("com", "edu", "org", "net", "mil", "gob")));
topMap.put( "hr", new HashSet<String>(Arrays.asList("iz.hr", "from.hr", "name.hr", "com.hr")));
topMap.put( "ht", new HashSet<String>(Arrays.asList("com", "shop", "firm", "info", "adult",
"net", "pro", "org", "med", "art", "coop", "pol", "asso", "edu", "rel", "gouv", "perso")));
topMap.put( "hu", new HashSet<String>(Arrays.asList("co", "info", "org", "priv", "sport", "tm",
"2000", "agrar", "bolt", "casino", "city", "erotica", "erotika", "film", "forum",
"games", "hotel", "ingatlan", "jogasz", "konyvelo", "lakas", "media", "news", "reklam",
"sex", "shop", "suli", "szex", "tozsde", "utazas", "video")));
topMap.put( "id", new HashSet<String>(Arrays.asList("ac", "co", "go", "mil", "net", "or", "sch",
"web")));
topMap.put( "im", new HashSet<String>(Arrays.asList("co.im", "com", "net.im", "gov.im", "org.im",
"ac.im")));
topMap.put( "in", new HashSet<String>(Arrays.asList("co", "firm", "ernet", "net", "org", "gen", "ind",
"nic", "ac", "edu", "res", "gov", "mil")));
topMap.put( "iq", new HashSet<String>(Arrays.asList("gov", "edu", "mil", "com", "org", "net" )));
topMap.put( "ir", new HashSet<String>(Arrays.asList("ac", "co", "gov", "id", "net", "org", "sch"
)));
topMap.put( "is", new HashSet<String>(Arrays.asList("net", "com", "edu", "gov", "org", "int")));
topMap.put( "it", new HashSet<String>(Arrays.asList("gov", "edu", "agrigento", "ag", "alessandria",
"al", "ancona", "an", "aosta", "aoste", "ao", "arezzo", "ar", "ascoli-piceno",
"ascolipiceno", "ap", "asti", "at", "avellino", "av", "bari", "ba",
"andria-barletta-trani", "andriabarlettatrani", "trani-barletta-andria",
"tranibarlettaandria", "barletta-trani-andria", "barlettatraniandria",
"andria-trani-barletta", "andriatranibarletta", "trani-andria-barletta",
"traniandriabarletta", "bt", "belluno", "bl", "benevento", "bn", "bergamo", "bg",
"biella", "bi", "bologna", "bo", "bolzano", "bozen", "balsan", "alto-adige",
"altoadige", "suedtirol", "bz", "brescia", "bs", "brindisi", "br", "cagliari",
"ca", "caltanissetta", "cl", "campobasso", "cb", "carboniaiglesias", "carbonia-iglesias",
"iglesias-carbonia", "iglesiascarbonia", "ci", "caserta", "ce", "catania", "ct",
"catanzaro", "cz", "chieti", "ch", "como", "co", "cosenza", "cs", "cremona", "cr",
"crotone", "kr", "cuneo", "cn", "dell-ogliastra", "dellogliastra", "ogliastra", "og",
"enna", "en", "ferrara", "fe", "fermo", "fm", "firenze", "florence", "fi", "foggia",
"fg", "forli-cesena", "forlicesena", "cesena-forli", "cesenaforli", "fc", "frosinone",
"fr", "genova", "genoa", "ge", "gorizia", "go", "grosseto", "gr", "imperia", "im",
"isernia", "is", "laquila", "aquila", "aq", "la-spezia", "laspezia", "sp", "latina",
"lt", "lecce", "le", "lecco", "lc", "livorno", "li", "lodi", "lo", "lucca", "lu",
"macerata", "mc", "mantova", "mn", "massa-carrara", "massacarrara", "carrara-massa",
"carraramassa", "ms", "matera", "mt", "medio-campidano", "mediocampidano",
"campidano-medio", "campidanomedio", "vs", "messina", "me", "milano", "milan",
"mi", "modena", "mo", "monza", "monza-brianza", "monzabrianza", "monzaebrianza",
"monzaedellabrianza", "monza-e-della-brianza", "mb", "napoli", "naples", "na",
"novara", "no", "nuoro", "nu", "oristano", "or", "padova", "padua", "pd", "palermo",
"pa", "parma", "pr", "pavia", "pv", "perugia", "pg", "pescara", "pe", "pesaro-urbino",
"pesarourbino", "urbino-pesaro", "urbinopesaro", "pu", "piacenza", "pc", "pisa",
"pi", "pistoia", "pt", "pordenone", "pn", "potenza", "pz", "prato", "po", "ragusa",
"rg", "ravenna", "ra", "reggio-calabria", "reggiocalabria", "rc", "reggio-emilia",
"reggioemilia", "re", "rieti", "ri", "rimini", "rn", "roma", "rome", "rm", "rovigo",
"ro", "salerno", "sa", "sassari", "ss", "savona", "sv", "siena", "si", "siracusa",
"sr", "sondrio", "so", "taranto", "ta", "tempio-olbia", "tempioolbia", "olbia-tempio",
"olbiatempio", "ot", "teramo", "te", "terni", "tr", "torino", "turin", "to",
"trapani", "tp", "trento", "trentino", "tn", "treviso", "tv", "trieste", "ts",
"udine", "ud", "varese", "va", "venezia", "venice", "ve", "verbania", "vb",
"vercelli", "vc", "verona", "vr", "vibo-valentia", "vibovalentia", "vv", "vicenza",
"vi", "viterbo", "vt")));
topMap.put( "je", new HashSet<String>(Arrays.asList("co", "org", "net", "sch", "gov")));
topMap.put( "jo", new HashSet<String>(Arrays.asList("com", "org", "net", "edu", "sch",
"gov", "mil", "name")));
topMap.put( "jp", new HashSet<String>(Arrays.asList("ac", "ad", "co", "ed", "go", "gr", "lg",
"ne", "or")));
topMap.put( "kg", new HashSet<String>(Arrays.asList("org", "net", "com", "edu", "gov", "mil")));
topMap.put( "ki", new HashSet<String>(Arrays.asList("edu", "biz", "net", "org", "gov",
"info", "com")));
topMap.put( "km", new HashSet<String>(Arrays.asList("org", "nom", "gov", "prd", "tm", "edu",
"mil", "ass", "com", "coop", "asso", "presse", "medecin", "notaires", "pharmaciens",
"veterinaire", "gouv")));
topMap.put( "kn", new HashSet<String>(Arrays.asList("net", "org", "edu", "gov")));
topMap.put( "kp", new HashSet<String>(Arrays.asList("com", "edu", "gov", "org", "rep", "tra")));
topMap.put( "kr", new HashSet<String>(Arrays.asList("ac", "co", "es", "go", "hs", "kg", "mil",
"ms", "ne", "or", "pe", "re", "sc", "busan", "chungbuk", "chungnam", "daegu",
"daejeon", "gangwon", "gwangju", "gyeongbuk", "gyeonggi", "gyeongnam", "incheon",
"jeju", "jeonbuk", "jeonnam", "seoul", "ulsan")));
topMap.put( "kz", new HashSet<String>(Arrays.asList("org", "edu", "net", "gov", "mil", "com")));
topMap.put( "la", new HashSet<String>(Arrays.asList("int", "net", "info", "edu", "gov", "per",
"com", "org", "c")));
topMap.put( "lc", new HashSet<String>(Arrays.asList("com", "net", "co", "org", "edu", "gov",
"l.lc", "p.lc")));
topMap.put( "lk", new HashSet<String>(Arrays.asList("gov", "sch", "net", "int", "com", "org",
"edu", "ngo", "soc", "web", "ltd", "assn", "grp", "hotel")));
topMap.put( "ls", new HashSet<String>(Arrays.asList("co", "gov", "ac", "org")));
topMap.put( "lv", new HashSet<String>(Arrays.asList("com", "edu", "gov", "org", "mil",
"id", "net", "asn", "conf")));
topMap.put( "ly", new HashSet<String>(Arrays.asList("com", "net", "gov", "plc", "edu", "sch",
"med", "org", "id")));
topMap.put( "ma", new HashSet<String>(Arrays.asList("co", "net", "gov", "org", "ac", "press")));
topMap.put( "me", new HashSet<String>(Arrays.asList("co", "net", "org", "edu", "ac", "gov",
"its", "priv")));
topMap.put( "mg", new HashSet<String>(Arrays.asList("org", "nom", "gov", "prd", "tm",
"edu", "mil", "com")));
topMap.put( "mk", new HashSet<String>(Arrays.asList("com", "org", "net", "edu", "gov", "inf",
"name", "pro")));
topMap.put( "ml", new HashSet<String>(Arrays.asList("com", "edu", "gouv", "gov", "net",
"org", "presse")));
topMap.put( "mn", new HashSet<String>(Arrays.asList("gov", "edu", "org")));
topMap.put( "mp", new HashSet<String>(Arrays.asList("gov", "co", "org")));
topMap.put( "mu", new HashSet<String>(Arrays.asList("com", "net", "org", "gov", "ac",
"co", "or")));
topMap.put( "museum", new HashSet<String>(Arrays.asList("academy", "agriculture", "air",
"airguard", "alabama", "alaska", "amber", "ambulance", "american", "americana",
"americanantiques", "americanart", "amsterdam", "and", "annefrank", "anthro",
"anthropology", "antiques", "aquarium", "arboretum", "archaeological", "archaeology",
"architecture", "art", "artanddesign", "artcenter", "artdeco", "arteducation",
"artgallery", "arts", "artsandcrafts", "asmatart", "assassination", "assisi",
"association", "astronomy", "atlanta", "austin", "australia", "automotive", "aviation",
"axis", "badajoz", "baghdad", "bahn", "bale", "baltimore", "barcelona", "baseball",
"basel", "baths", "bauern", "beauxarts", "beeldengeluid", "bellevue", "bergbau",
"berkeley", "berlin", "bern", "bible", "bilbao", "bill", "birdart", "birthplace",
"bonn", "boston", "botanical", "botanicalgarden", "botanicgarden", "botany",
"brandywinevalley", "brasil", "bristol", "british", "britishcolumbia", "broadcast",
"brunel", "brussel", "brussels", "bruxelles", "building", "burghof", "bus", "bushey",
"cadaques", "california", "cambridge", "can", "canada", "capebreton", "carrier",
"cartoonart", "casadelamoneda", "castle", "castres", "celtic", "center", "chattanooga",
"cheltenham", "chesapeakebay", "chicago", "children", "childrens", "childrensgarden",
"chiropractic", "chocolate", "christiansburg", "cincinnati", "cinema", "circus",
"civilisation", "civilization", "civilwar", "clinton", "clock", "coal", "coastaldefence",
"cody", "coldwar", "collection", "colonialwilliamsburg", "coloradoplateau", "columbia",
"columbus", "communication", "communications", "community", "computer",
"computerhistory", "xn--comunicaes-v6a2o", "contemporary", "contemporaryart",
"convent", "copenhagen", "corporation", "xn--correios-e-telecomunicaes-ghc29a",
"corvette", "costume", "countryestate", "county", "crafts", "cranbrook", "creation",
"cultural", "culturalcenter", "culture", "cyber", "cymru", "dali", "dallas", "database",
"ddr", "decorativearts", "delaware", "delmenhorst", "denmark", "depot", "design",
"detroit", "dinosaur", "discovery", "dolls", "donostia", "durham", "eastafrica",
"eastcoast", "education", "educational", "egyptian", "eisenbahn", "elburg",
"elvendrell", "embroidery", "encyclopedic", "england", "entomology", "environment",
"environmentalconservation", "epilepsy", "essex", "estate", "ethnology", "exeter",
"exhibition", "family", "farm", "farmequipment", "farmers", "farmstead", "field",
"figueres", "filatelia", "film", "fineart", "finearts", "finland", "flanders", "florida",
"force", "fortmissoula", "fortworth", "foundation", "francaise", "frankfurt",
"franziskaner", "freemasonry", "freiburg", "fribourg", "frog", "fundacio", "furniture",
"gallery", "garden", "gateway", "geelvinck", "gemological", "geology", "georgia",
"giessen", "glas", "glass", "gorge", "grandrapids", "graz", "guernsey", "halloffame",
"hamburg", "handson", "harvestcelebration", "hawaii", "health", "heimatunduhren",
"hellas", "helsinki", "hembygdsforbund", "heritage", "histoire", "historical",
"historicalsociety", "historichouses", "historisch", "historisches", "history",
"historyofscience", "horology", "house", "humanities", "illustration", "imageandsound",
"indian", "indiana", "indianapolis", "indianmarket", "intelligence", "interactive",
"iraq", "iron", "isleofman", "jamison", "jefferson", "jerusalem", "jewelry",
"jewish", "jewishart", "jfk", "journalism", "judaica", "judygarland", "juedisches",
"juif", "karate", "karikatur", "kids", "koebenhavn", "koeln", "kunst", "kunstsammlung",
"kunstunddesign", "labor", "labour", "lajolla", "lancashire", "landes", "lans",
"xn--lns-qla", "larsson", "lewismiller", "lincoln", "linz", "living", "livinghistory",
"localhistory", "london", "losangeles", "louvre", "loyalist", "lucerne", "luxembourg",
"luzern", "mad", "madrid", "mallorca", "manchester", "mansion", "mansions", "manx",
"marburg", "maritime", "maritimo", "maryland", "marylhurst", "media", "medical",
"medizinhistorisches", "meeres", "memorial", "mesaverde", "michigan", "midatlantic",
"military", "mill", "miners", "mining", "minnesota", "missile", "missoula", "modern",
"moma", "money", "monmouth", "monticello", "montreal", "moscow", "motorcycle", "muenchen",
"muenster", "mulhouse", "muncie", "museet", "museumcenter", "museumvereniging", "music",
"national", "nationalfirearms", "nationalheritage", "nativeamerican", "naturalhistory",
"naturalhistorymuseum", "naturalsciences", "nature", "naturhistorisches",
"natuurwetenschappen", "naumburg", "naval", "nebraska", "neues", "newhampshire",
"newjersey", "newmexico", "newport", "newspaper", "newyork", "niepce", "norfolk",
"north", "nrw", "nuernberg", "nuremberg", "nyc", "nyny", "oceanographic",
"oceanographique", "omaha", "online", "ontario", "openair", "oregon", "oregontrail",
"otago", "oxford", "pacific", "paderborn", "palace", "paleo", "palmsprings", "panama",
"paris", "pasadena", "pharmacy", "philadelphia", "philadelphiaarea", "philately",
"phoenix", "photography", "pilots", "pittsburgh", "planetarium", "plantation",
"plants", "plaza", "portal", "portland", "portlligat", "posts-and-telecommunications",
"preservation", "presidio", "press", "project", "public", "pubol", "quebec",
"railroad", "railway", "research", "resistance", "riodejaneiro", "rochester", "rockart",
"roma", "russia", "saintlouis", "salem", "salvadordali", "salzburg", "sandiego",
"sanfrancisco", "santabarbara", "santacruz", "santafe", "saskatchewan", "satx",
"savannahga", "schlesisches", "schoenbrunn", "schokoladen", "school", "schweiz",
"science", "scienceandhistory", "scienceandindustry", "sciencecenter", "sciencecenters",
"science-fiction", "sciencehistory", "sciences", "sciencesnaturelles", "scotland",
"seaport", "settlement", "settlers", "shell", "sherbrooke", "sibenik", "silk", "ski",
"skole", "society", "sologne", "soundandvision", "southcarolina", "southwest", "space",
"spy", "square", "stadt", "stalbans", "starnberg", "state", "stateofdelaware",
"station", "steam", "steiermark", "stjohn", "stockholm", "stpetersburg", "stuttgart",
"suisse", "surgeonshall", "surrey", "svizzera", "sweden", "sydney", "tank", "tcm",
"technology", "telekommunikation", "television", "texas", "textile", "theater",
"time", "timekeeping", "topology", "torino", "touch", "town", "transport", "tree",
"trolley", "trust", "trustee", "uhren", "ulm", "undersea", "university", "usa",
"usantiques", "usarts", "uscountryestate", "usculture", "usdecorativearts", "usgarden",
"ushistory", "ushuaia", "uslivinghistory", "utah", "uvic", "valley", "vantaa",
"versailles", "viking", "village", "virginia", "virtual", "virtuel", "vlaanderen",
"volkenkunde", "wales", "wallonie", "war", "washingtondc", "watchandclock",
"watch-and-clock", "western", "westfalen", "whaling", "wildlife", "williamsburg",
"windmill", "workshop", "york", "yorkshire", "yosemite", "youth", "zoological",
"zoology", "xn--9dbhblg6di", "xn--h1aegh")));
topMap.put( "mv", new HashSet<String>(Arrays.asList("aero", "biz", "com", "coop", "edu", "gov",
"info", "int", "mil", "museum", "name", "net", "org", "pro")));
topMap.put( "mw", new HashSet<String>(Arrays.asList("ac", "biz", "co", "com", "coop", "edu",
"gov", "int", "museum", "net", "org")));
topMap.put( "mx", new HashSet<String>(Arrays.asList("com", "org", "gob", "edu", "net")));
topMap.put( "my", new HashSet<String>(Arrays.asList("com", "net", "org", "gov", "edu",
"mil", "name", "sch")));
topMap.put( "na", new HashSet<String>(Arrays.asList("co", "com", "org", "edu", "edunet", "net",
"alt", "biz", "info")));
topMap.put( "nc", new HashSet<String>(Arrays.asList("asso", "nom")));
topMap.put( "net", new HashSet<String>(Arrays.asList("gb", "se", "uk", "za")));
topMap.put( "ng", new HashSet<String>(Arrays.asList("name", "sch", "mil", "mobi", "com",
"edu", "gov", "net", "org")));
topMap.put( "nf", new HashSet<String>(Arrays.asList("com", "net", "per", "rec", "web",
"arts", "firm", "info", "other", "store")));
topMap.put( "no", new HashSet<String>(Arrays.asList("fhs", "vgs", "fylkesbibl", "folkebibl",
"museum", "idrett", "priv", "mil", "stat", "dep", "kommune", "herad", "aa",
"ah", "bu", "fm", "hl", "hm", "jan-mayen", "mr", "nl", "nt", "of", "ol", "oslo",
"rl", "sf", "st", "svalbard", "tm", "tr", "va", "vf", "akrehamn",
"xn--krehamn-dxa", "algard", "xn--lgrd-poac", "arna", "brumunddal",
"bryne", "bronnoysund", "xn--brnnysund-m8ac", "drobak",
"xn--drbak-wua", "egersund", "fetsund", "floro", "xn--flor-jra",
"fredrikstad", "hokksund", "honefoss", "xn--hnefoss-q1a",
"jessheim", "jorpeland", "xn--jrpeland-54a", "kirkenes", "kopervik",
"krokstadelva", "langevag", "xn--langevg-jxa", "leirvik", "mjondalen",
"xn--mjndalen-64a", "mo-i-rana", "mosjoen", "xn--mosjen-eya",
"nesoddtangen", "orkanger", "osoyro", "xn--osyro-wua",
"raholt", "xn--rholt-mra", "sandnessjoen", "xn--sandnessjen-ogb",
"skedsmokorset", "slattum", "spjelkavik", "stathelle", "stavern", "stjordalshalsen",
"xn--stjrdalshalsen-sqb", "tananger", "tranby", "vossevangen", "tranby",
"vossevangen", "afjord", "xn--fjord-lra", "agdenes", "al",
"xn--l-1fa", "alesund", "xn--lesund-hua",
"alstahaug", "alta", "xn--lt-liac", "alaheadju",
"xn--laheadju-7ya", "alvdal", "amli", "xn--mli-tla",
"amot", "xn--mot-tla", "andebu", "andoy", "xn--andy-ira",
"andasuolo", "ardal", "xn--rdal-poa", "aremark", "arendal",
"xn--s-1fa", "aseral", "xn--seral-lra",
"asker", "askim", "askvoll", "askoy", "xn--asky-ira",
"asnes", "xn--snes-poa", "audnedaln", "aukra", "aure", "aurland",
"aurskog-holand", "xn--aurskog-hland-jnb",
"austevoll", "austrheim", "averoy", "xn--avery-yua",
"balestrand", "ballangen", "balat", "xn--blt-elab",
"balsfjord", "bahccavuotna", "xn--bhccavuotna-k7a",
"bamble", "bardu", "beardu", "beiarn", "bajddar", "xn--bjddar-pta",
"baidar", "xn--bidr-5nac", "berg", "bergen", "berlevag", "xn--berlevg-jxa",
"bearalvahki", "xn--bearalvhki-y4a", "bindal", "birkenes", "bjarkoy",
"xn--bjarky-fya", "bjerkreim", "bjugn", "bodo", "xn--bod-2na",
"badaddja", "xn--bdddj-mrabd", "budejju", "bokn",
"bremanger", "bronnoy", "xn--brnny-wuac", "bygland",
"bykle", "barum", "xn--brum-voa", "bievat", "xn--bievt-0qa",
"bomlo", "xn--bmlo-gra", "batsfjord", "xn--btsfjord-9za", "bahcavuotna",
"xn--bhcavuotna-s4a", "dovre", "drammen", "drangedal", "dyroy",
"xn--dyry-ira", "donna", "xn--dnna-gra",
"eid", "eidfjord", "eidsberg", "eidskog", "eidsvoll", "eigersund", "elverum",
"enebakk", "engerdal", "etne", "etnedal", "evenes", "evenassi",
"xn--eveni-0qa01ga", "evje-og-hornnes", "farsund", "fauske",
"fuossko", "fuoisku", "fedje", "fet", "finnoy", "xn--finny-yua",
"fitjar", "fjaler", "fjell", "flakstad", "flatanger", "flekkefjord", "flesberg",
"flora", "fla", "xn--fl-zia", "folldal", "forsand", "fosnes", "frei",
"frogn", "froland", "frosta", "frana", "xn--frna-woa",
"froya", "xn--frya-hra", "fusa", "fyresdal", "forde",
"xn--frde-gra", "gamvik", "gangaviika", "xn--ggaviika-8ya47h",
"gaular", "gausdal", "gildeskal", "xn--gildeskl-g0a",
"giske", "gjemnes", "gjerdrum", "gjerstad", "gjesdal", "gjovik",
"xn--gjvik-wua", "gloppen", "gol", "gran", "grane", "granvin",
"gratangen", "grimstad", "grong", "kraanghke", "xn--kranghke-b0a",
"grue", "gulen", "hadsel", "halden", "halsa", "hamar", "hamaroy", "habmer",
"xn--hbmer-xqa", "hapmir", "xn--hpmir-xqa",
"hammerfest", "hammarfeasta", "xn--hmmrfeasta-s4ac",
"haram", "hareid", "harstad", "hasvik", "aknoluokta", "xn--koluokta-7ya57h",
"hattfjelldal", "aarborte", "haugesund", "hemne", "hemnes", "hemsedal",
"hitra", "hjartdal", "hjelmeland",
"hobol", "xn--hobl-ira", "hof", "hol", "hole", "holmestrand", "holtalen",
"xn--holtlen-hxa", "hornindal", "horten", "hurdal", "hurum", "hvaler",
"hyllestad", "hagebostad", "xn--hgebostad-g3a", "hoyanger",
"xn--hyanger-q1a", "hoylandet", "xn--hylandet-54a",
"ha", "xn--h-2fa", "ibestad", "inderoy", "xn--indery-fya",
"iveland", "jevnaker", "jondal", "jolster", "xn--jlster-bya",
"karasjok", "karasjohka", "xn--krjohka-hwab49j",
"karlsoy", "galsa", "xn--gls-elac", "karmoy",
"xn--karmy-yua", "kautokeino", "guovdageaidnu", "klepp", "klabu",
"xn--klbu-woa", "kongsberg", "kongsvinger", "kragero", "xn--krager-gya",
"kristiansand", "kristiansund", "krodsherad", "xn--krdsherad-m8a",
"kvalsund", "rahkkeravju", "xn--rhkkervju-01af",
"kvam", "kvinesdal", "kvinnherad", "kviteseid", "kvitsoy", "xn--kvitsy-fya",
"kvafjord", "xn--kvfjord-nxa", "giehtavuoatna", "kvanangen",
"xn--kvnangen-k0a", "navuotna", "xn--nvuotna-hwa",
"kafjord", "xn--kfjord-iua", "gaivuotna", "xn--givuotna-8ya",
"larvik", "lavangen", "lavagis", "loabat", "xn--loabt-0qa",
"lebesby", "davvesiida", "leikanger", "leirfjord", "leka", "leksvik", "lenvik",
"leangaviika", "xn--leagaviika-52b", "lesja", "levanger", "lier", "lierne",
"lillehammer", "lillesand", "lindesnes", "lindas", "xn--linds-pra",
"lom", "loppa", "lahppi", "xn--lhppi-xqa", "lund", "lunner", "luroy",
"xn--lury-ira", "luster", "lyngdal", "lyngen", "ivgu", "lardal", "lerdal",
"xn--lrdal-sra", "lodingen", "xn--ldingen-q1a", "lorenskog",
"xn--lrenskog-54a", "loten", "xn--lten-gra", "malvik",
"masoy", "xn--msy-ula0h", "muosat", "xn--muost-0qa",
"mandal", "marker", "marnardal", "masfjorden", "meland", "meldal", "melhus",
"meloy", "xn--mely-ira", "meraker", "xn--merker-kua", "moareke",
"xn--moreke-jua", "midsund", "midtre-gauldal", "modalen", "modum",
"molde", "moskenes", "moss", "mosvik", "malselv", "xn--mlselv-iua",
"malatvuopmi", "xn--mlatvuopmi-s4a", "namdalseid", "aejrie", "namsos",
"namsskogan", "naamesjevuemie", "xn--nmesjevuemie-tcba",
"laakesvuemie", "nannestad", "narvik", "narviika", "naustdal", "nedre-eiker",
"nesna", "nesodden", "nesseby", "unjarga", "xn--unjrga-rta", "nesset",
"nissedal", "nittedal", "nord-aurdal", "nord-fron", "nord-odal", "norddal",
"nordkapp", "davvenjarga", "xn--davvenjrga-y4a", "nordre-land",
"nordreisa", "raisa", "xn--risa-5na", "nore-og-uvdal", "notodden", "naroy",
"xn--nry-yla5g", "notteroy", "xn--nttery-byae",
"odda", "oksnes", "xn--ksnes-uua", "oppdal", "oppegard",
"xn--oppegrd-ixa", "orkdal", "orland", "xn--rland-uua",
"orskog", "xn--rskog-uua", "orsta", "xn--rsta-fra",
"os.hedmark", "os.hordaland", "osen", "osteroy", "xn--ostery-fya",
"ostre-toten", "xn--stre-toten-zcb", "overhalla", "ovre-eiker",
"xn--vre-eiker-k8a", "oyer", "xn--yer-zna",
"oygarden", "xn--ygarden-p1a", "oystre-slidre", "xn--ystre-slidre-ujb",
"porsanger", "porsangu", "xn--porsgu-sta26f", "porsgrunn",
"radoy", "xn--rady-ira", "rakkestad", "rana", "ruovat", "randaberg",
"rauma", "rendalen", "rennebu", "rennesoy", "xn--rennesy-v1a",
"rindal", "ringebu", "ringerike", "ringsaker", "rissa", "risor",
"xn--risr-ira", "roan", "rollag", "rygge", "ralingen", "xn--rlingen-mxa",
"rodoy", "xn--rdy-0nab", "romskog", "xn--rmskog-bya",
"roros", "xn--rros-gra", "rost", "xn--rst-0na",
"royken", "xn--ryken-vua", "royrvik", "xn--ryrvik-bya",
"rade", "xn--rde-ula", "salangen", "siellak", "saltdal", "salat",
"xn--slt-elab", "xn--slat-5na", "samnanger",
"sandefjord", "sandnes", "sandoy", "xn--sandy-yua", "sarpsborg",
"sauda", "sauherad", "sel", "selbu", "selje", "seljord", "sigdal", "siljan",
"sirdal", "skaun", "skedsmo", "ski", "skien", "skiptvet", "skjervoy",
"xn--skjervy-v1a", "skierva", "xn--skierv-uta",
"skjak", "xn--skjk-soa", "skodje", "skanland", "xn--sknland-fxa",
"skanit", "xn--sknit-yqa", "smola", "xn--smla-hra",
"snillfjord", "snasa", "xn--snsa-roa", "snoasa", "snaase",
"xn--snase-nra", "sogndal", "sokndal", "sola", "solund", "songdalen",
"sortland", "spydeberg", "stange", "stavanger", "steigen", "steinkjer",
"stjordal", "xn--stjrdal-s1a", "stokke", "stor-elvdal", "stord", "stordal",
"storfjord", "omasvuotna", "strand", "stranda", "stryn", "sula", "suldal",
"sund", "sunndal", "surnadal", "sveio", "svelvik", "sykkylven", "sogne",
"xn--sgne-gra", "somna", "xn--smna-gra", "sondre-land",
"xn--sndre-land-0cb", "sor-aurdal", "xn--sr-aurdal-l8a",
"sor-fron", "xn--sr-fron-q1a", "sor-odal", "xn--sr-odal-q1a",
"sor-varanger", "xn--sr-varanger-ggb", "matta-varjjat",
"xn--mtta-vrjjat-k7af", "sorfold", "xn--srfold-bya",
"sorreisa", "xn--srreisa-q1a", "sorum", "xn--srum-gra",
"tana", "deatnu", "time", "tingvoll", "tinn", "tjeldsund", "dielddanuorri",
"tjome", "xn--tjme-hra", "tokke", "tolga", "torsken", "tranoy",
"xn--trany-yua", "tromso", "xn--troms-zua", "tromsa", "romsa",
"trondheim", "troandin", "trysil", "trana", "xn--trna-woa",
"trogstad", "xn--trgstad-r1a", "tvedestrand", "tydal", "tynset",
"tysfjord", "divtasvuodna", "divttasvuotna", "tysnes", "tysvar",
"xn--tysvr-vra", "tonsberg", "xn--tnsberg-q1a",
"ullensaker", "ullensvang", "ulvik", "utsira", "vadso", "xn--vads-jra",
"cahcesuolo", "xn--hcesuolo-7ya35b", "vaksdal", "valle", "vang",
"vanylven", "vardo", "xn--vard-jra", "varggat", "xn--vrggt-xqad",
"vefsn", "vaapste", "vega", "vegarshei", "xn--vegrshei-c0a", "vennesla",
"verdal", "verran", "vestby", "vestnes", "vestre-slidre", "vestre-toten",
"vestvagoy", "xn--vestvgy-ixa6o", "vevelstad", "vik", "vikna",
"vindafjord", "volda", "voss", "varoy", "xn--vry-yla5g",
"vagan", "xn--vgan-qoa", "voagat", "vagsoy", "xn--vgsy-qoa0j",
"vaga", "xn--vg-yiab")));
topMap.put( "nr", new HashSet<String>(Arrays.asList("biz", "info", "gov", "edu", "org",
"net", "com", "co")));
topMap.put( "pa", new HashSet<String>(Arrays.asList("ac", "gob", "com", "org",
"sld", "edu", "net", "ing", "abo", "med", "nom")));
topMap.put( "pe", new HashSet<String>(Arrays.asList("edu", "gob", "nom", "mil", "org", "com",
"net", "sld")));
topMap.put( "pf", new HashSet<String>(Arrays.asList( "com")));
topMap.put( "ph", new HashSet<String>(Arrays.asList("com", "net", "org", "gov", "edu", "ngo", "mil")));
topMap.put( "pk", new HashSet<String>(Arrays.asList("com", "net", "edu", "org", "fam", "biz",
"web", "gov", "gob", "gok", "gon", "gop", "gos", "gog", "gkp", "info")));
topMap.put( "pl", new HashSet<String>(Arrays.asList("aid", "agro", "atm", "auto", "biz", "com",
"edu", "gmina", "gsm", "info", "mail", "miasta", "media", "mil", "net", "nieruchomosci",
"nom", "org", "pc", "powiat", "priv", "realestate", "rel", "sex", "shop", "sklep",
"sos", "szkola", "targi", "tm", "tourism", "travel", "turystyka", "art",
"gov", "ngo", "augustow", "babia-gora", "bedzin", "beskidy",
"bialowieza", "bialystok", "bielawa", "bieszczady", "boleslawiec", "bydgoszcz",
"bytom", "cieszyn", "czeladz", "czest", "dlugoleka", "elblag", "elk", "glogow",
"gniezno", "gorlice", "grajewo", "ilawa", "jaworzno", "jelenia-gora", "jgora",
"kalisz", "kazimierz-dolny", "karpacz", "kartuzy", "kaszuby", "katowice", "kepno",
"ketrzyn", "klodzko", "kobierzyce", "kolobrzeg", "konin", "konskowola", "kutno",
"lapy", "lebork", "legnica", "lezajsk", "limanowa", "lomza", "lowicz", "lubin",
"lukow", "malbork", "malopolska", "mazowsze", "mazury", "mielec", "mielno", "mragowo",
"naklo", "nowaruda", "nysa", "olawa", "olecko", "olkusz", "olsztyn", "opoczno",
"opole", "ostroda", "ostroleka", "ostrowiec", "ostrowwlkp", "pila", "pisz", "podhale",
"podlasie", "polkowice", "pomorze", "pomorskie", "prochowice", "pruszkow", "przeworsk",
"pulawy", "radom", "rawa-maz", "rybnik", "rzeszow", "sanok", "sejny", "siedlce",
"slask", "slupsk", "sosnowiec", "stalowa-wola", "skoczow", "starachowice", "stargard",
"suwalki", "swidnica", "swiebodzin", "swinoujscie", "szczecin", "szczytno", "tarnobrzeg",
"tgory", "turek", "tychy", "ustka", "walbrzych", "warmia", "warszawa", "waw",
"wegrow", "wielun", "wlocl", "wloclawek", "wodzislaw", "wolomin", "wroclaw",
"zachpomor", "zagan", "zarow", "zgora", "zgorzelec", "gda", "gdansk",
"krakow", "poznan", "wroc", "co",
"lodz", "lublin", "torun")));
topMap.put( "pn", new HashSet<String>(Arrays.asList("gov", "co", "org", "edu", "net")));
topMap.put( "pr", new HashSet<String>(Arrays.asList("com", "net", "org", "gov", "edu", "isla",
"pro", "biz", "info", "name", "est", "prof", "ac", "gobierno")));
topMap.put( "pro", new HashSet<String>(Arrays.asList("aca", "bar", "cpa", "jur", "law",
"med", "eng")));
topMap.put( "ps", new HashSet<String>(Arrays.asList("edu", "gov", "sec", "plo", "com", "org", "net")));
topMap.put( "pt", new HashSet<String>(Arrays.asList("net", "gov", "org", "edu", "int", "publ",
"com", "nome")));
topMap.put( "pw", new HashSet<String>(Arrays.asList("co", "ne", "or", "ed", "go", "belau")));
topMap.put( "qa", new HashSet<String>(Arrays.asList("com", "net", "org", "gov", "edu", "mil")));
topMap.put( "re", new HashSet<String>(Arrays.asList("com", "asso", "nom")));
topMap.put( "ro", new HashSet<String>(Arrays.asList("com", "org", "tm", "nt", "nom", "info",
"rec", "arts", "firm", "store", "www")));
topMap.put( "rs", new HashSet<String>(Arrays.asList("co", "org", "edu", "ac", "gov", "in")));
topMap.put( "ru", new HashSet<String>(Arrays.asList("ac", "com", "edu", "int", "net", "org",
"pp", "adygeya", "altai", "amur", "arkhangelsk", "astrakhan", "bashkiria",
"belgorod", "bir", "bryansk", "buryatia", "cap", "cbg", "chel", "chelyabinsk", "chita",
"chukotka", "dagestan", "e-burg", "grozny", "irkutsk",
"ivanovo", "izhevsk", "jar", "joshkar-ola", "kalmykia", "kaluga", "kamchatka",
"karelia", "kazan", "kchr", "kemerovo", "khabarovsk", "khakassia", "khv", "kirov",
"koenig", "komi", "kostroma", "krasnoyarsk", "kuban", "kurgan", "kursk", "lipetsk",
"magadan", "mari", "mari-el", "marine", "mordovia", "mosreg", "msk", "murmansk",
"nalchik", "nnov", "nov", "novosibirsk", "nsk", "omsk", "orenburg", "oryol",
"palana", "penza", "perm", "pskov", "ptz", "rnd", "ryazan", "sakhalin", "samara",
"saratov", "simbirsk", "smolensk", "spb", "stavropol", "stv", "surgut", "tambov",
"tatarstan", "tom", "tomsk", "tsaritsyn", "tsk", "tula", "tuva", "tver", "tyumen",
"udm", "udmurtia", "ulan-ude", "vladikavkaz", "vladimir", "vladivostok", "volgograd",
"vologda", "voronezh", "vrn", "vyatka", "yakutia", "yamal", "yaroslavl",
"yekaterinburg", "yuzhno-sakhalinsk", "amursk", "baikal", "cmw", "fareast",
"jamal", "kms", "k-uralsk", "kustanai", "kuzbass", "magnitka", "mytis",
"nakhodka", "nkz", "norilsk", "oskol", "pyatigorsk", "rubtsovsk", "snz", "syzran",
"vdonsk", "zgrad", "gov", "mil", "test")));
topMap.put( "rw", new HashSet<String>(Arrays.asList("gov", "net", "edu", "ac", "com", "co",
"int", "mil", "gouv")));
topMap.put( "sa", new HashSet<String>(Arrays.asList("com", "net", "org", "gov", "med", "pub",
"edu", "sch")));
topMap.put( "sd", new HashSet<String>(Arrays.asList("com", "net", "org", "edu", "med", "gov",
"info", "tv")));
topMap.put( "se", new HashSet<String>(Arrays.asList("a", "ac", "b", "bd", "brand", "c", "d",
"e", "f", "fh", "fhsk", "fhv", "g", "h", "i", "k", "komforb", "kommunalforbund",
"komvux", "l", "lanarb", "lanbib", "m", "n", "naturbruksgymn", "o", "org", "p", "parti",
"pp", "press", "r", "s", "sshn", "t", "tm", "u", "w", "x", "y", "z")));
topMap.put( "sg", new HashSet<String>(Arrays.asList("com", "net", "org", "gov", "edu", "per")));
topMap.put( "sh", new HashSet<String>(Arrays.asList("co", "com", "net", "org", "gov", "edu", "nom")));
topMap.put( "sk", new HashSet<String>(Arrays.asList("gov", "edu")));
topMap.put( "sn", new HashSet<String>(Arrays.asList("art", "com", "edu", "gouv", "org", "perso",
"univ")));
topMap.put( "so", new HashSet<String>(Arrays.asList("com", "net", "org")));
topMap.put( "sr", new HashSet<String>(Arrays.asList("co", "com", "consulado", "edu", "embaixada",
"gov", "mil", "net", "org", "principe", "saotome", "store")));
topMap.put( "sy", new HashSet<String>(Arrays.asList("edu", "gov", "net", "mil", "com", "org", "news")));
topMap.put( "sz", new HashSet<String>(Arrays.asList("co", "ac", "org")));
topMap.put( "th", new HashSet<String>(Arrays.asList("ac", "co", "go", "in", "mi", "net", "or")));
topMap.put( "tj", new HashSet<String>(Arrays.asList("ac", "biz", "co", "com", "edu", "go", "gov",
"int", "mil", "name", "net", "nic", "org", "test", "web")));
topMap.put( "tn", new HashSet<String>(Arrays.asList("com", "ens", "fin", "gov", "ind", "intl",
"nat", "net", "org", "info", "perso", "tourism", "edunet", "rnrt", "rns", "rnu",
"mincom", "agrinet", "defense", "turen")));
topMap.put( "to", new HashSet<String>(Arrays.asList("gov")));
topMap.put( "tt", new HashSet<String>(Arrays.asList("co", "com", "org", "net", "biz", "info",
"pro", "int", "coop", "jobs", "mobi", "travel", "museum", "aero", "name", "gov",
"edu", "cat", "tel", "mil")));
topMap.put( "tw", new HashSet<String>(Arrays.asList("edu", "gov", "mil", "com", "net", "org",
"idv", "game", "ebiz", "club", "xn--zf0ao64a", "xn--uc0atv", "xn--czrw28b")));
topMap.put( "ua", new HashSet<String>(Arrays.asList("com", "edu", "gov", "in", "net", "org",
"cherkassy", "chernigov", "chernovtsy", "ck", "cn", "crimea", "cv", "dn",
"dnepropetrovsk", "donetsk", "dp", "if", "ivano-frankivsk", "kh", "kharkov",
"kherson", "kiev", "kirovograd", "km", "kr", "ks", "lg",
"lugansk", "lutsk", "lviv", "mk", "nikolaev", "od", "odessa", "pl", "poltava",
"rovno", "rv", "sebastopol", "sumy", "te", "ternopil", "uzhgorod", "vinnica", "vn",
"zaporizhzhe", "zp", "zhitomir", "zt", "cr", "lt", "lv", "sb", "sm", "tr",
"co", "biz", "in", "ne", "pp", "uz", "dominic")));
topMap.put( "ug", new HashSet<String>(Arrays.asList("co", "ac", "sc", "go", "ne", "or", "org", "com")));
topMap.put( "us", new HashSet<String>(Arrays.asList("dni", "fed", "isa", "kids", "nsn", "kyschools")));
topMap.put( "uz", new HashSet<String>(Arrays.asList("co", "com", "org", "gov", "ac", "edu", "int", "pp", "net")));
topMap.put( "vc", new HashSet<String>(Arrays.asList("com", "net", "org", "gov")));
topMap.put( "vi", new HashSet<String>(Arrays.asList("co", "com", "k12", "net", "org")));
topMap.put( "vn", new HashSet<String>(Arrays.asList( "com", "net", "org", "edu", "gov", "int",
"ac", "biz", "info", "name", "pro", "health")));
topMap.put( "vu", new HashSet<String>(Arrays.asList("co", "com", "net", "org", "edu", "gov", "de")));
topMap.put("org", new HashSet<String>(Arrays.asList("ae", "za")));
topMap.put("pro", new HashSet<String>(Arrays.asList("aca", "bar", "cpa", "jur", "law", "med", "eng")));
top3Map.put("au", new HashSet<String>(Arrays.asList("act.edu.au", "eq.edu.au",
"nsw.edu.au", "nt.edu.au", "qld.edu.au", "sa.edu.au", "tas.edu.au", "vic.edu.au",
"wa.edu.au", "act.gov.au", "nsw.gov.au", "nt.gov.au", "qld.gov.au", "sa.gov.au",
"tas.gov.au", "vic.gov.au", "wa.gov.au")));
top3Map.put("im", new HashSet<String>(Arrays.asList("ltd.co.im", "plc.co.im")));
top3Map.put("no", new HashSet<String>(Arrays.asList("gs.aa.no", "gs.ah.no", "gs.bu.no",
"gs.fm.no", "gs.hl.no", "gs.hm.no", "gs.jan-mayen.no", "gs.mr.no", "gs.nl.no",
"gs.nt.no", "gs.of.no", "gs.ol.no", "gs.oslo.no", "gs.rl.no", "gs.sf.no",
"gs.st.no", "gs.svalbard.no", "gs.tm.no", "gs.tr.no", "gs.va.no", "gs.vf.no",
"bo.telemark.no", "xn--b-5ga.telemark.no", "bo.nordland.no",
"xn--b-5ga.nordland.no", "heroy.more-og-romsdal.no",
"xn--hery-ira.xn--mre-og-romsdal-qqb.no", "heroy.nordland.no",
"xn--hery-ira.nordland.no", "nes.akershus.no", "nes.buskerud.no",
"os.hedmark.no", "os.hordaland.no",
"sande.more-og-romsdal.no", "sande.xn--mre-og-romsdal-qqb.no",
"sande.vestfold.no", "valer.ostfold.no", "xn--vler-qoa.xn--stfold-9xa.no",
"valer.hedmark.no", "xn--vler-qoa.hedmark.no")));
top3Map.put("tr", new HashSet<String>(Arrays.asList("gov.nc.tr")));
}
/*
* Return the registered part of a qualified domain
* name or the original if no match is found.
*/
public static String getRegisteredDomain(String cname) {
int dot;
/*
* If one dot or less than just return.
*/
dot = cname.lastIndexOf('.');
if (dot == -1)
return cname;
if (dot == 0)
return "";
if (dot == cname.length() - 1) {
cname = cname.substring(0, cname.length() -1);
dot = cname.lastIndexOf('.');
if (dot == -1)
return cname;
if (dot == 0)
return "";
}
if (dot == cname.length() - 1)
return "";
/*
* Break it up into seperate labels.
*/
int second = cname.lastIndexOf('.', dot - 1);
if (second == -1)
return cname;
if (second == 0)
return "";
int third = cname.lastIndexOf('.', second - 1);
int fourth = -1;
if (third > 0) {
fourth = cname.lastIndexOf('.', third - 1);
}
int fifth = -1;
if (fourth > 0) {
fifth = cname.lastIndexOf('.', fourth - 1);
}
String s = cname.substring(dot + 1);
String s2 = cname.substring(second + 1, dot);
/*
* Look for longest matches first.
* XX.PVT.K12.MA.US etc.
*/
if (fourth != -1 && s.equals("us") && usStateSet.contains(s2)) {
String s3 = cname.substring(third + 1, second);
String s4 = cname.substring(fourth + 1, third);
if (s3.equals("k12")) {
if (s2.equals("ma") && (s4.equals("chtr") || s4.equals("paroch"))) {
return cname.substring(fifth + 1);
} else if (s4.equals("pvt")) {
return cname.substring(fifth + 1);
}
}
}
/*
* XX.K12.MA.US.
*/
String str = cname.substring(third + 1);
if (third != -1) {
Set set = top3Map.get(s);
if (set != null) {
if (set.contains(str)) {
return cname.substring(fourth + 1);
}
} else if (s.equals("us") && usStateSet.contains(s2)) {
// check for known third level labels
String s3 = cname.substring(third + 1, second);
if (usSubStateSet.contains(s3)) {
return fourth != -1? cname.substring(fourth + 1): cname;
} else {
return cname.substring(third + 1);
}
} else if (s.equals("uk")) {
if (s2.equals("sch")) {
return cname.substring(fourth + 1);
}
} else if (s.equals("jp")) {
if (jpSet.contains(s2)) {
if (jp2Set.contains(str)) {
return cname.substring(third + 1);
}
return cname.substring(fourth + 1);
}
}
}
/*
* PREF.AKITA.JP etc.
*/
if (jp2Set.contains(str)) {
return cname.substring(third + 1);
}
/*
* XX.MA.US.
*/
Set topSet = topMap.get(s);
if (topSet != null) {
if (topSet.contains(s2)) {
return cname.substring(third + 1);
}
if (!((s.equals("us") && usStateSet.contains(s2)) || (s.equals("jp") && jpSet.contains(s2)))) {
return cname.substring(second + 1);
}
} else if (top2Set.contains(s)) {
if (s2.equals("gov")) {
return cname.substring(third + 1);
}
return cname.substring(second + 1);
} else if (top3Set.contains(s)) {
if (s.equals("ad") && s2.equals("nom") ||
s.equals("aw") && s2.equals("com") ||
s.equals("be") && s2.equals("ac") ||
s.equals("cl") && s2.equals("gov") ||
s.equals("cl") && s2.equals("gob") ||
s.equals("fi") && s2.equals("aland") ||
s.equals("int") && s2.equals("eu") ||
s.equals("io") && s2.equals("com") ||
s.equals("mc") && s2.equals("tm") ||
s.equals("mc") && s2.equals("asso") ||
s.equals("vc") && s2.equals("com")) {
return cname.substring(third + 1);
}
return cname.substring(second + 1);
} else if (top4Set.contains(s)) {
if (s2.equals("com") || s2.equals("edu") || s2.equals("gov") ||
s2.equals("net") || s2.equals("org")) {
return cname.substring(third + 1);
}
return cname.substring(second + 1);
} else if (top5Set.contains(s)) {
return cname.substring(third + 1);
}
/*
* BB.AA exception cases.
*/
if (s.equals("tr")) {
if (!s2.equals("nic") && !s2.equals("tsk")) {
return cname.substring(third + 1);
}
return cname.substring(second + 1);
} else if (s.equals("uk")) {
if (!ukSet.contains(s2)) {
return cname.substring(third + 1);
}
return cname.substring(second + 1);
} else if (s.equals("ar")) {
if (!arSet.contains(s2)) {
return cname.substring(third + 1);
}
return cname.substring(second + 1);
} else if (s.equals("om")) {
if (!omSet.contains(s2)) {
return cname.substring(third + 1);
}
return cname.substring(second + 1);
}
/*
* XX.AA
*/
if (top1Set.contains(s)) {
return cname.substring(second + 1);
}
/*
* Nothing matched so we can't shorten the string.
*/
return cname;
}
}

View File

@ -238,4 +238,14 @@ abstract public class URLConnection extends java.net.URLConnection {
public void close() { public void close() {
url = null; url = null;
} }
private static HashMap<String,Void> proxiedHosts = new HashMap<>();
public synchronized static void setProxiedHost(String host) {
proxiedHosts.put(host.toLowerCase(), null);
}
public synchronized static boolean isProxiedHost(String host) {
return proxiedHosts.containsKey(host.toLowerCase());
}
} }

View File

@ -301,7 +301,11 @@ public class HttpClient extends NetworkClient {
} else { } else {
SecurityManager security = System.getSecurityManager(); SecurityManager security = System.getSecurityManager();
if (security != null) { if (security != null) {
security.checkConnect(url.getHost(), url.getPort()); if (ret.proxy == Proxy.NO_PROXY || ret.proxy == null) {
security.checkConnect(InetAddress.getByName(url.getHost()).getHostAddress(), url.getPort());
} else {
security.checkConnect(url.getHost(), url.getPort());
}
} }
ret.url = url; ret.url = url;
} }
@ -457,6 +461,7 @@ public class HttpClient extends NetworkClient {
protected synchronized void openServer() throws IOException { protected synchronized void openServer() throws IOException {
SecurityManager security = System.getSecurityManager(); SecurityManager security = System.getSecurityManager();
if (security != null) { if (security != null) {
security.checkConnect(host, port); security.checkConnect(host, port);
} }
@ -469,6 +474,7 @@ public class HttpClient extends NetworkClient {
url.getProtocol().equals("https") ) { url.getProtocol().equals("https") ) {
if ((proxy != null) && (proxy.type() == Proxy.Type.HTTP)) { if ((proxy != null) && (proxy.type() == Proxy.Type.HTTP)) {
sun.net.www.URLConnection.setProxiedHost(host);
privilegedOpenServer((InetSocketAddress) proxy.address()); privilegedOpenServer((InetSocketAddress) proxy.address());
usingProxy = true; usingProxy = true;
return; return;
@ -484,6 +490,7 @@ public class HttpClient extends NetworkClient {
* ftp url. * ftp url.
*/ */
if ((proxy != null) && (proxy.type() == Proxy.Type.HTTP)) { if ((proxy != null) && (proxy.type() == Proxy.Type.HTTP)) {
sun.net.www.URLConnection.setProxiedHost(host);
privilegedOpenServer((InetSocketAddress) proxy.address()); privilegedOpenServer((InetSocketAddress) proxy.address());
usingProxy = true; usingProxy = true;
return; return;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2011, 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
@ -653,6 +653,13 @@ final class Config {
} }
} }
debug(keyword + ": " + lib); debug(keyword + ": " + lib);
// Check to see if full path is specified to prevent the DLL
// preloading attack
if (!(new File(lib)).isAbsolute()) {
throw new ConfigurationException(
"Absolute path required for library value: " + lib);
}
return lib; return lib;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2011, 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
@ -236,7 +236,8 @@ public final class Secmod {
throw new IllegalStateException(e); throw new IllegalStateException(e);
} }
if (modules == null) { if (modules == null) {
List<Module> modules = (List<Module>)nssGetModuleList(nssHandle); List<Module> modules = (List<Module>)nssGetModuleList(nssHandle,
nssLibDir);
this.modules = Collections.unmodifiableList(modules); this.modules = Collections.unmodifiableList(modules);
} }
return modules; return modules;
@ -358,7 +359,7 @@ public final class Secmod {
* A representation of one PKCS#11 slot in a PKCS#11 module. * A representation of one PKCS#11 slot in a PKCS#11 module.
*/ */
public static final class Module { public static final class Module {
// name of the native library // path of the native library
final String libraryName; final String libraryName;
// descriptive name used by NSS // descriptive name used by NSS
final String commonName; final String commonName;
@ -371,8 +372,10 @@ public final class Secmod {
// trust attributes. Used for the KEYSTORE and TRUSTANCHOR modules only // trust attributes. Used for the KEYSTORE and TRUSTANCHOR modules only
private Map<Bytes,TrustAttributes> trust; private Map<Bytes,TrustAttributes> trust;
Module(String libraryName, String commonName, boolean fips, int slot) { Module(String libraryDir, String libraryName, String commonName,
boolean fips, int slot) {
ModuleType type; ModuleType type;
if ((libraryName == null) || (libraryName.length() == 0)) { if ((libraryName == null) || (libraryName.length() == 0)) {
// must be softtoken // must be softtoken
libraryName = System.mapLibraryName(SOFTTOKEN_LIB_NAME); libraryName = System.mapLibraryName(SOFTTOKEN_LIB_NAME);
@ -397,7 +400,7 @@ public final class Secmod {
+ "module: " + libraryName + ", " + commonName); + "module: " + libraryName + ", " + commonName);
} }
} }
this.libraryName = libraryName; this.libraryName = (new File(libraryDir, libraryName)).getPath();
this.commonName = commonName; this.commonName = commonName;
this.slot = slot; this.slot = slot;
this.type = type; this.type = type;
@ -752,6 +755,6 @@ public final class Secmod {
private static native boolean nssInit(String functionName, long handle, String configDir); private static native boolean nssInit(String functionName, long handle, String configDir);
private static native Object nssGetModuleList(long handle); private static native Object nssGetModuleList(long handle, String libDir);
} }

View File

@ -1790,15 +1790,30 @@ public class PolicyFile extends java.security.Policy {
CodeSource canonCs = cs; CodeSource canonCs = cs;
URL u = cs.getLocation(); URL u = cs.getLocation();
if (u != null && u.getProtocol().equals("file")) { if (u != null) {
boolean isLocalFile = false; if (u.getProtocol().equals("jar")) {
String host = u.getHost(); // unwrap url embedded inside jar url
isLocalFile = (host == null || host.equals("") || String spec = u.getFile();
host.equals("~") || host.equalsIgnoreCase("localhost")); int separator = spec.indexOf("!/");
if (separator != -1) {
try {
u = new URL(spec.substring(0, separator));
} catch (MalformedURLException e) {
// Fail silently. In this case, url stays what
// it was above
}
}
}
if (u.getProtocol().equals("file")) {
boolean isLocalFile = false;
String host = u.getHost();
isLocalFile = (host == null || host.equals("") ||
host.equals("~") || host.equalsIgnoreCase("localhost"));
if (isLocalFile) { if (isLocalFile) {
path = u.getFile().replace('/', File.separatorChar); path = u.getFile().replace('/', File.separatorChar);
path = ParseUtil.decode(path); path = ParseUtil.decode(path);
}
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006, 2010 Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2006, 2010, 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

View File

@ -28,6 +28,7 @@
#include "jni.h" #include "jni.h"
#include "jvm.h" #include "jvm.h"
#include "jdk_util_md.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@ -1971,6 +1971,13 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage
return data->abortFlag; return data->abortFlag;
} }
if (cinfo->output_components <= 0 ||
cinfo->image_width > (0xffffffffu / (unsigned int)cinfo->output_components))
{
JNU_ThrowByName(env, "javax/imageio/IIOException",
"Invalid number of output components");
return data->abortFlag;
}
// Allocate a 1-scanline buffer // Allocate a 1-scanline buffer
scanLinePtr = (JSAMPROW)malloc(cinfo->image_width*cinfo->output_components); scanLinePtr = (JSAMPROW)malloc(cinfo->image_width*cinfo->output_components);

View File

@ -367,7 +367,7 @@ static double euclidianDistance(double a, double b) {
JNIEXPORT jlong JNICALL JNIEXPORT jlong JNICALL
Java_sun_font_FreetypeFontScaler_createScalerContextNative( Java_sun_font_FreetypeFontScaler_createScalerContextNative(
JNIEnv *env, jobject scaler, jlong pScaler, jdoubleArray matrix, JNIEnv *env, jobject scaler, jlong pScaler, jdoubleArray matrix,
jboolean ttFont, jint aa, jint fm, jfloat boldness, jfloat italic) { jint aa, jint fm, jfloat boldness, jfloat italic) {
double dmat[4], ptsz; double dmat[4], ptsz;
FTScalerContext *context = FTScalerContext *context =
(FTScalerContext*) calloc(1, sizeof(FTScalerContext)); (FTScalerContext*) calloc(1, sizeof(FTScalerContext));

View File

@ -186,7 +186,11 @@ JNIEXPORT void JNICALL Java_sun_font_SunLayoutEngine_nativeLayout
jchar buffer[256]; jchar buffer[256];
jchar* chars = buffer; jchar* chars = buffer;
if (len > 256) { if (len > 256) {
chars = (jchar*)malloc(len * sizeof(jchar)); size_t size = len * sizeof(jchar);
if (size / sizeof(jchar) != len) {
return;
}
chars = (jchar*)malloc(size);
if (chars == 0) { if (chars == 0) {
return; return;
} }

View File

@ -233,9 +233,19 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_loadProfile
jint dataSize; jint dataSize;
storeID_t sProf; storeID_t sProf;
if (JNU_IsNull(env, data)) {
JNU_ThrowIllegalArgumentException(env, "Invalid profile data");
return 0L;
}
dataArray = (*env)->GetByteArrayElements (env, data, 0); dataArray = (*env)->GetByteArrayElements (env, data, 0);
dataSize = (*env)->GetArrayLength (env, data); dataSize = (*env)->GetArrayLength (env, data);
if (dataArray == NULL) {
JNU_ThrowIllegalArgumentException(env, "Invalid profile data");
return 0L;
}
sProf.pf = cmsOpenProfileFromMem((const void *)dataArray, sProf.pf = cmsOpenProfileFromMem((const void *)dataArray,
(cmsUInt32Number) dataSize); (cmsUInt32Number) dataSize);
@ -334,8 +344,9 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileData
} }
/* Get profile header info */ /* Get profile header info */
cmsBool _getHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize); static cmsBool _getHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize);
cmsBool _setHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize); static cmsBool _setHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize);
static cmsBool _writeCookedTag(cmsHPROFILE pfTarget, cmsTagSignature sig, jbyte *pData, jint size);
/* /*
* Class: sun_java2d_cmm_lcms_LCMS * Class: sun_java2d_cmm_lcms_LCMS
@ -356,7 +367,7 @@ JNIEXPORT jint JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagSize
result = sizeof(cmsICCHeader); result = sizeof(cmsICCHeader);
} else { } else {
if (cmsIsTag(sProf.pf, sig.cms)) { if (cmsIsTag(sProf.pf, sig.cms)) {
result = cmsReadRawTag(sProf.pf, sig.cms, NULL, 0); result = cmsReadRawTag(sProf.pf, sig.cms, NULL, 0);
} else { } else {
JNU_ThrowByName(env, "java/awt/color/CMMException", JNU_ThrowByName(env, "java/awt/color/CMMException",
"ICC profile tag not found"); "ICC profile tag not found");
@ -468,22 +479,30 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_setTagData
sProf.j = id; sProf.j = id;
sig.j = tagSig; sig.j = tagSig;
if (JNU_IsNull(env, data)) {
JNU_ThrowIllegalArgumentException(env, "Can not write tag data.");
return;
}
tagSize =(*env)->GetArrayLength(env, data); tagSize =(*env)->GetArrayLength(env, data);
dataArray = (*env)->GetByteArrayElements(env, data, 0); dataArray = (*env)->GetByteArrayElements(env, data, 0);
if (dataArray == NULL) {
JNU_ThrowIllegalArgumentException(env, "Can not write tag data.");
return;
}
if (tagSig == SigHead) { if (tagSig == SigHead) {
status = _setHeaderInfo(sProf.pf, dataArray, tagSize); status = _setHeaderInfo(sProf.pf, dataArray, tagSize);
} else { } else {
status = cmsWriteRawTag(sProf.pf, sig.cms, dataArray, tagSize); status = _writeCookedTag(sProf.pf, sig.cms, dataArray, tagSize);
} }
(*env)->ReleaseByteArrayElements(env, data, dataArray, 0); (*env)->ReleaseByteArrayElements(env, data, dataArray, 0);
if (!status) { if (!status) {
JNU_ThrowByName(env, "java/awt/color/CMMException", JNU_ThrowIllegalArgumentException(env, "Can not write tag data.");
"Can not write tag data.");
} }
} }
@ -645,7 +664,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_initLCMS
PF_ID_fID = (*env)->GetFieldID (env, Pf, "ID", "J"); PF_ID_fID = (*env)->GetFieldID (env, Pf, "ID", "J");
} }
cmsBool _getHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize) static cmsBool _getHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize)
{ {
cmsUInt32Number pfSize = 0; cmsUInt32Number pfSize = 0;
cmsUInt8Number* pfBuffer = NULL; cmsUInt8Number* pfBuffer = NULL;
@ -672,7 +691,7 @@ cmsBool _getHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize)
return status; return status;
} }
cmsBool _setHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize) static cmsBool _setHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize)
{ {
cmsICCHeader pfHeader = { 0 }; cmsICCHeader pfHeader = { 0 };
@ -696,3 +715,77 @@ cmsBool _setHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize)
return TRUE; return TRUE;
} }
static cmsBool _writeCookedTag(cmsHPROFILE pfTarget,
cmsTagSignature sig,
jbyte *pData, jint size)
{
cmsBool status;
cmsUInt32Number pfSize = 0;
cmsUInt8Number* pfBuffer = NULL;
cmsHPROFILE p = cmsCreateProfilePlaceholder(NULL);
if (NULL != p) {
cmsICCHeader hdr = { 0 };
/* Populate the placeholder's header according to target profile */
hdr.flags = cmsGetHeaderFlags(pfTarget);
hdr.renderingIntent = cmsGetHeaderRenderingIntent(pfTarget);
hdr.manufacturer = cmsGetHeaderManufacturer(pfTarget);
hdr.model = cmsGetHeaderModel(pfTarget);
hdr.pcs = cmsGetPCS(pfTarget);
hdr.colorSpace = cmsGetColorSpace(pfTarget);
hdr.deviceClass = cmsGetDeviceClass(pfTarget);
hdr.version = cmsGetEncodedICCversion(pfTarget);
cmsGetHeaderAttributes(pfTarget, &hdr.attributes);
cmsGetHeaderProfileID(pfTarget, (cmsUInt8Number*)&hdr.profileID);
cmsSetHeaderFlags(p, hdr.flags);
cmsSetHeaderManufacturer(p, hdr.manufacturer);
cmsSetHeaderModel(p, hdr.model);
cmsSetHeaderAttributes(p, hdr.attributes);
cmsSetHeaderProfileID(p, (cmsUInt8Number*)&(hdr.profileID));
cmsSetHeaderRenderingIntent(p, hdr.renderingIntent);
cmsSetPCS(p, hdr.pcs);
cmsSetColorSpace(p, hdr.colorSpace);
cmsSetDeviceClass(p, hdr.deviceClass);
cmsSetEncodedICCversion(p, hdr.version);
if (cmsWriteRawTag(p, sig, pData, size)) {
if (cmsSaveProfileToMem(p, NULL, &pfSize)) {
pfBuffer = malloc(pfSize);
if (pfBuffer != NULL) {
/* load raw profile data into the buffer */
if (!cmsSaveProfileToMem(p, pfBuffer, &pfSize)) {
free(pfBuffer);
pfBuffer = NULL;
}
}
}
}
cmsCloseProfile(p);
}
if (pfBuffer == NULL) {
return FALSE;
}
/* re-open the placeholder profile */
p = cmsOpenProfileFromMem(pfBuffer, pfSize);
free(pfBuffer);
status = FALSE;
if (p != NULL) {
/* Note that pCookedTag points to internal structures of the placeholder,
* so this data is valid only while the placeholder is open.
*/
void *pCookedTag = cmsReadTag(p, sig);
if (pCookedTag != NULL) {
status = cmsWriteTag(pfTarget, sig, pCookedTag);
}
pCookedTag = NULL;
cmsCloseProfile(p);
}
return status;
}

View File

@ -1636,6 +1636,11 @@ cmsInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig
TagDescriptor = _cmsGetTagDescriptor(sig); TagDescriptor = _cmsGetTagDescriptor(sig);
// Serialize // Serialize
if (!_cmsWriteTypeBase(MemIO, TypeHandler ->Signature)) {
cmsCloseIOhandler(MemIO);
return 0;
}
if (!TypeHandler ->WritePtr(TypeHandler, MemIO, Object, TagDescriptor ->ElemCount)) return 0; if (!TypeHandler ->WritePtr(TypeHandler, MemIO, Object, TagDescriptor ->ElemCount)) return 0;
// Get Size and close // Get Size and close

View File

@ -74,6 +74,94 @@ static TransformInterpFunc BicubicInterpStub;
TransformInterpFunc *pBilinearFunc = BilinearInterp; TransformInterpFunc *pBilinearFunc = BilinearInterp;
TransformInterpFunc *pBicubicFunc = BicubicInterp; TransformInterpFunc *pBicubicFunc = BicubicInterp;
/*
* The dxydxy parameters of the inverse transform determine how
* quickly we step through the source image. For tiny scale
* factors (on the order of 1E-16 or so) the stepping distances
* are huge. The image has been scaled so small that stepping
* a single pixel in device space moves the sampling point by
* billions (or more) pixels in the source image space. These
* huge stepping values can overflow the whole part of the longs
* we use for the fixed point stepping equations and so we need
* a more robust solution. We could simply iterate over every
* device pixel, use the inverse transform to transform it back
* into the source image coordinate system and then test it for
* being in range and sample pixel-by-pixel, but that is quite
* a bit more expensive. Fortunately, if the scale factors are
* so tiny that we overflow our long values then the number of
* pixels we are planning to visit should be very tiny. The only
* exception to that rule is if the scale factor along one
* dimension is tiny (creating the huge stepping values), and
* the scale factor along the other dimension is fairly regular
* or an up-scale. In that case we have a lot of pixels along
* the direction of the larger axis to sample, but few along the
* smaller axis. Though, pessimally, with an added shear factor
* such a linearly tiny image could have bounds that cover a large
* number of pixels. Such odd transformations should be very
* rare and the absolute limit on calculations would involve a
* single reverse transform of every pixel in the output image
* which is not fast, but it should not cause an undue stall
* of the rendering software.
*
* The specific test we will use is to calculate the inverse
* transformed values of every corner of the destination bounds
* (in order to be user-clip independent) and if we can
* perform a fixed-point-long inverse transform of all of
* those points without overflowing we will use the fast
* fixed point algorithm. Otherwise we will use the safe
* per-pixel transform algorithm.
* The 4 corners are 0,0, 0,dsth, dstw,0, dstw,dsth
* Transformed they are:
* tx, ty
* tx +dxdy*H, ty +dydy*H
* tx+dxdx*W, ty+dydx*W
* tx+dxdx*W+dxdy*H, ty+dydx*W+dydy*H
*/
/* We reject coordinates not less than 1<<30 so that the distance between */
/* any 2 of them is less than 1<<31 which would overflow into the sign */
/* bit of a signed long value used to represent fixed point coordinates. */
#define TX_FIXED_UNSAFE(v) (fabs(v) >= (1<<30))
static jboolean
checkOverflow(jint dxoff, jint dyoff,
SurfaceDataBounds *pBounds,
TransformInfo *pItxInfo,
jdouble *retx, jdouble *rety)
{
jdouble x, y;
x = dxoff+pBounds->x1+0.5; /* Center of pixel x1 */
y = dyoff+pBounds->y1+0.5; /* Center of pixel y1 */
Transform_transform(pItxInfo, &x, &y);
*retx = x;
*rety = y;
if (TX_FIXED_UNSAFE(x) || TX_FIXED_UNSAFE(y)) {
return JNI_TRUE;
}
x = dxoff+pBounds->x2-0.5; /* Center of pixel x2-1 */
y = dyoff+pBounds->y1+0.5; /* Center of pixel y1 */
Transform_transform(pItxInfo, &x, &y);
if (TX_FIXED_UNSAFE(x) || TX_FIXED_UNSAFE(y)) {
return JNI_TRUE;
}
x = dxoff+pBounds->x1+0.5; /* Center of pixel x1 */
y = dyoff+pBounds->y2-0.5; /* Center of pixel y2-1 */
Transform_transform(pItxInfo, &x, &y);
if (TX_FIXED_UNSAFE(x) || TX_FIXED_UNSAFE(y)) {
return JNI_TRUE;
}
x = dxoff+pBounds->x2-0.5; /* Center of pixel x2-1 */
y = dyoff+pBounds->y2-0.5; /* Center of pixel y2-1 */
Transform_transform(pItxInfo, &x, &y);
if (TX_FIXED_UNSAFE(x) || TX_FIXED_UNSAFE(y)) {
return JNI_TRUE;
}
return JNI_FALSE;
}
/* /*
* Fill the edge buffer with pairs of coordinates representing the maximum * Fill the edge buffer with pairs of coordinates representing the maximum
* left and right pixels of the destination surface that should be processed * left and right pixels of the destination surface that should be processed
@ -82,21 +170,19 @@ TransformInterpFunc *pBicubicFunc = BicubicInterp;
* Only pixels that map back through the specified (inverse) transform to a * Only pixels that map back through the specified (inverse) transform to a
* source coordinate that falls within the (0, 0, sw, sh) bounds of the * source coordinate that falls within the (0, 0, sw, sh) bounds of the
* source image should be processed. * source image should be processed.
* pEdgeBuf points to an array of jints that holds MAXEDGES*2 values. * pEdges points to an array of jints that holds 2 + numedges*2 values where
* If more storage is needed, then this function allocates a new buffer. * numedges should match (pBounds->y2 - pBounds->y1).
* In either case, a pointer to the buffer actually used to store the * The first two jints in pEdges should be set to y1 and y2 and every pair
* results is returned. * of jints after that represent the xmin,xmax of all pixels in range of
* The caller is responsible for freeing the buffer if the return value * the transformed blit for the corresponding scanline.
* is not the same as the original pEdgeBuf passed in.
*/ */
static jint * static void
calculateEdges(jint *pEdgeBuf, calculateEdges(jint *pEdges,
SurfaceDataBounds *pBounds, SurfaceDataBounds *pBounds,
TransformInfo *pItxInfo, TransformInfo *pItxInfo,
jlong xbase, jlong ybase, jlong xbase, jlong ybase,
juint sw, juint sh) juint sw, juint sh)
{ {
jint *pEdges;
jlong dxdxlong, dydxlong; jlong dxdxlong, dydxlong;
jlong dxdylong, dydylong; jlong dxdylong, dydylong;
jlong drowxlong, drowylong; jlong drowxlong, drowylong;
@ -111,10 +197,8 @@ calculateEdges(jint *pEdgeBuf,
dy1 = pBounds->y1; dy1 = pBounds->y1;
dx2 = pBounds->x2; dx2 = pBounds->x2;
dy2 = pBounds->y2; dy2 = pBounds->y2;
if ((dy2-dy1) > MAXEDGES) { *pEdges++ = dy1;
pEdgeBuf = malloc(2 * (dy2-dy1) * sizeof (*pEdges)); *pEdges++ = dy2;
}
pEdges = pEdgeBuf;
drowxlong = (dx2-dx1-1) * dxdxlong; drowxlong = (dx2-dx1-1) * dxdxlong;
drowylong = (dx2-dx1-1) * dydxlong; drowylong = (dx2-dx1-1) * dydxlong;
@ -155,10 +239,22 @@ calculateEdges(jint *pEdgeBuf,
ybase += dydylong; ybase += dydylong;
dy1++; dy1++;
} }
return pEdgeBuf;
} }
static void
Transform_SafeHelper(JNIEnv *env,
SurfaceDataOps *srcOps,
SurfaceDataOps *dstOps,
SurfaceDataRasInfo *pSrcInfo,
SurfaceDataRasInfo *pDstInfo,
NativePrimitive *pMaskBlitPrim,
CompositeInfo *pCompInfo,
TransformHelperFunc *pHelperFunc,
TransformInterpFunc *pInterpFunc,
RegionData *pClipInfo, TransformInfo *pItxInfo,
jint *pData, jint *pEdges,
jint dxoff, jint dyoff, jint sw, jint sh);
/* /*
* Class: sun_java2d_loops_TransformHelper * Class: sun_java2d_loops_TransformHelper
* Method: Transform * Method: Transform
@ -187,12 +283,14 @@ Java_sun_java2d_loops_TransformHelper_Transform
jint maxlinepix; jint maxlinepix;
TransformHelperFunc *pHelperFunc; TransformHelperFunc *pHelperFunc;
TransformInterpFunc *pInterpFunc; TransformInterpFunc *pInterpFunc;
jint edgebuf[MAXEDGES * 2]; jdouble xorig, yorig;
jint numedges;
jint *pEdges; jint *pEdges;
jdouble x, y; jint edgebuf[2 + MAXEDGES * 2];
jlong xbase, ybase; union {
jlong dxdxlong, dydxlong; jlong align;
jlong dxdylong, dydylong; jint data[LINE_SIZE];
} rgb;
#ifdef MAKE_STUBS #ifdef MAKE_STUBS
static int th_initialized; static int th_initialized;
@ -269,39 +367,62 @@ Java_sun_java2d_loops_TransformHelper_Transform
if (srcOps->Lock(env, srcOps, &srcInfo, pHelperPrim->srcflags) if (srcOps->Lock(env, srcOps, &srcInfo, pHelperPrim->srcflags)
!= SD_SUCCESS) != SD_SUCCESS)
{ {
/* edgeArray should already contain zeros for min/maxy */
return; return;
} }
if (dstOps->Lock(env, dstOps, &dstInfo, pMaskBlitPrim->dstflags) if (dstOps->Lock(env, dstOps, &dstInfo, pMaskBlitPrim->dstflags)
!= SD_SUCCESS) != SD_SUCCESS)
{ {
SurfaceData_InvokeUnlock(env, srcOps, &srcInfo); SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
/* edgeArray should already contain zeros for min/maxy */
return; return;
} }
Region_IntersectBounds(&clipInfo, &dstInfo.bounds); Region_IntersectBounds(&clipInfo, &dstInfo.bounds);
Transform_GetInfo(env, itxform, &itxInfo); numedges = (dstInfo.bounds.y2 - dstInfo.bounds.y1);
dxdxlong = DblToLong(itxInfo.dxdx); if (numedges > MAXEDGES) {
dydxlong = DblToLong(itxInfo.dydx); pEdges = malloc((2 + 2 * numedges) * sizeof (*pEdges));
dxdylong = DblToLong(itxInfo.dxdy); if (pEdges == NULL) {
dydylong = DblToLong(itxInfo.dydy); SurfaceData_InvokeUnlock(env, dstOps, &dstInfo);
x = dxoff+dstInfo.bounds.x1+0.5; /* Center of pixel x1 */ SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
y = dyoff+dstInfo.bounds.y1+0.5; /* Center of pixel y1 */ /* edgeArray should already contain zeros for min/maxy */
Transform_transform(&itxInfo, &x, &y); return;
xbase = DblToLong(x); }
ybase = DblToLong(y); } else {
pEdges = edgebuf;
}
pEdges = calculateEdges(edgebuf, &dstInfo.bounds, &itxInfo, Transform_GetInfo(env, itxform, &itxInfo);
xbase, ybase, sx2-sx1, sy2-sy1);
if (!Region_IsEmpty(&clipInfo)) { if (!Region_IsEmpty(&clipInfo)) {
srcOps->GetRasInfo(env, srcOps, &srcInfo); srcOps->GetRasInfo(env, srcOps, &srcInfo);
dstOps->GetRasInfo(env, dstOps, &dstInfo); dstOps->GetRasInfo(env, dstOps, &dstInfo);
if (srcInfo.rasBase && dstInfo.rasBase) { if (srcInfo.rasBase == NULL || dstInfo.rasBase == NULL) {
union { pEdges[0] = pEdges[1] = 0;
jlong align; } else if (checkOverflow(dxoff, dyoff, &dstInfo.bounds,
jint data[LINE_SIZE]; &itxInfo, &xorig, &yorig))
} rgb; {
Transform_SafeHelper(env, srcOps, dstOps,
&srcInfo, &dstInfo,
pMaskBlitPrim, &compInfo,
pHelperFunc, pInterpFunc,
&clipInfo, &itxInfo, rgb.data, pEdges,
dxoff, dyoff, sx2-sx1, sy2-sy1);
} else {
SurfaceDataBounds span; SurfaceDataBounds span;
jlong dxdxlong, dydxlong;
jlong dxdylong, dydylong;
jlong xbase, ybase;
dxdxlong = DblToLong(itxInfo.dxdx);
dydxlong = DblToLong(itxInfo.dydx);
dxdylong = DblToLong(itxInfo.dxdy);
dydylong = DblToLong(itxInfo.dydy);
xbase = DblToLong(xorig);
ybase = DblToLong(yorig);
calculateEdges(pEdges, &dstInfo.bounds, &itxInfo,
xbase, ybase, sx2-sx1, sy2-sy1);
Region_StartIteration(env, &clipInfo); Region_StartIteration(env, &clipInfo);
while (Region_NextIteration(&clipInfo, &span)) { while (Region_NextIteration(&clipInfo, &span)) {
@ -318,8 +439,8 @@ Java_sun_java2d_loops_TransformHelper_Transform
/* Note - process at most one scanline at a time. */ /* Note - process at most one scanline at a time. */
dx1 = pEdges[(dy1 - dstInfo.bounds.y1) * 2]; dx1 = pEdges[(dy1 - dstInfo.bounds.y1) * 2 + 2];
dx2 = pEdges[(dy1 - dstInfo.bounds.y1) * 2 + 1]; dx2 = pEdges[(dy1 - dstInfo.bounds.y1) * 2 + 3];
if (dx1 < span.x1) dx1 = span.x1; if (dx1 < span.x1) dx1 = span.x1;
if (dx2 > span.x2) dx2 = span.x2; if (dx2 > span.x2) dx2 = span.x2;
@ -376,21 +497,124 @@ Java_sun_java2d_loops_TransformHelper_Transform
} }
SurfaceData_InvokeRelease(env, dstOps, &dstInfo); SurfaceData_InvokeRelease(env, dstOps, &dstInfo);
SurfaceData_InvokeRelease(env, srcOps, &srcInfo); SurfaceData_InvokeRelease(env, srcOps, &srcInfo);
} else {
pEdges[0] = pEdges[1] = 0;
} }
SurfaceData_InvokeUnlock(env, dstOps, &dstInfo); SurfaceData_InvokeUnlock(env, dstOps, &dstInfo);
SurfaceData_InvokeUnlock(env, srcOps, &srcInfo); SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
if (!JNU_IsNull(env, edgeArray)) { if (!JNU_IsNull(env, edgeArray)) {
(*env)->SetIntArrayRegion(env, edgeArray, 0, 1, &dstInfo.bounds.y1); (*env)->SetIntArrayRegion(env, edgeArray, 0, 2+numedges*2, pEdges);
(*env)->SetIntArrayRegion(env, edgeArray, 1, 1, &dstInfo.bounds.y2);
(*env)->SetIntArrayRegion(env, edgeArray,
2, (dstInfo.bounds.y2 - dstInfo.bounds.y1)*2,
pEdges);
} }
if (pEdges != edgebuf) { if (pEdges != edgebuf) {
free(pEdges); free(pEdges);
} }
} }
static void
Transform_SafeHelper(JNIEnv *env,
SurfaceDataOps *srcOps,
SurfaceDataOps *dstOps,
SurfaceDataRasInfo *pSrcInfo,
SurfaceDataRasInfo *pDstInfo,
NativePrimitive *pMaskBlitPrim,
CompositeInfo *pCompInfo,
TransformHelperFunc *pHelperFunc,
TransformInterpFunc *pInterpFunc,
RegionData *pClipInfo, TransformInfo *pItxInfo,
jint *pData, jint *pEdges,
jint dxoff, jint dyoff, jint sw, jint sh)
{
SurfaceDataBounds span;
jint dx1, dx2;
jint dy1, dy2;
jint i, iy;
dy1 = pDstInfo->bounds.y1;
dy2 = pDstInfo->bounds.y2;
dx1 = pDstInfo->bounds.x1;
dx2 = pDstInfo->bounds.x2;
pEdges[0] = dy1;
pEdges[1] = dy2;
for (iy = dy1; iy < dy2; iy++) {
jint i = (iy - dy1) * 2;
/* row spans are set to max,min until we find a pixel in range below */
pEdges[i + 2] = dx2;
pEdges[i + 3] = dx1;
}
Region_StartIteration(env, pClipInfo);
while (Region_NextIteration(pClipInfo, &span)) {
dy1 = span.y1;
dy2 = span.y2;
while (dy1 < dy2) {
dx1 = span.x1;
dx2 = span.x2;
i = (dy1 - pDstInfo->bounds.y1) * 2;
while (dx1 < dx2) {
jdouble x, y;
jlong xlong, ylong;
x = dxoff + dx1 + 0.5;
y = dyoff + dy1 + 0.5;
Transform_transform(pItxInfo, &x, &y);
xlong = DblToLong(x);
ylong = DblToLong(y);
/* Process only pixels with centers in bounds
* Test double values to avoid overflow in conversion
* to long values and then also test the long values
* in case they rounded up and out of bounds during
* the conversion.
*/
if (x >= 0 && y >= 0 && x < sw && y < sh &&
WholeOfLong(xlong) < sw &&
WholeOfLong(ylong) < sh)
{
void *pDst;
if (pEdges[i + 2] > dx1) {
pEdges[i + 2] = dx1;
}
if (pEdges[i + 3] <= dx1) {
pEdges[i + 3] = dx1 + 1;
}
/* Get IntArgbPre pixel data from source */
(*pHelperFunc)(pSrcInfo,
pData, 1,
xlong, 0,
ylong, 0);
/* Interpolate result pixels if needed */
if (pInterpFunc) {
(*pInterpFunc)(pData, 1,
FractOfLong(xlong-LongOneHalf), 0,
FractOfLong(ylong-LongOneHalf), 0);
}
/* Store/Composite interpolated pixels into dest */
pDst = PtrCoord(pDstInfo->rasBase,
dx1, pDstInfo->pixelStride,
dy1, pDstInfo->scanStride);
(*pMaskBlitPrim->funcs.maskblit)(pDst, pData,
0, 0, 0,
1, 1,
pDstInfo, pSrcInfo,
pMaskBlitPrim,
pCompInfo);
}
/* Increment to next input pixel */
dx1++;
}
/* Increment to next scanline */
dy1++;
}
}
Region_EndIteration(env, pClipInfo);
}
#define BL_INTERP_V1_to_V2_by_F(v1, v2, f) \ #define BL_INTERP_V1_to_V2_by_F(v1, v2, f) \
(((v1)<<8) + ((v2)-(v1))*(f)) (((v1)<<8) + ((v2)-(v1))*(f))

View File

@ -1,30 +1,27 @@
/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* ********************************************************************* /* *********************************************************************
*
* Sun elects to have this file available under and governed by the
* Mozilla Public License Version 1.1 ("MPL") (see
* http://www.mozilla.org/MPL/ for full license text). For the avoidance
* of doubt and subject to the following, Sun also elects to allow
* licensees to use this file under the MPL, the GNU General Public
* License version 2 only or the Lesser General Public License version
* 2.1 only. Any references to the "GNU General Public License version 2
* or later" or "GPL" in the following shall be construed to mean the
* GNU General Public License version 2 only. Any references to the "GNU
* Lesser General Public License version 2.1 or later" or "LGPL" in the
* following shall be construed to mean the GNU Lesser General Public
* License version 2.1 only. However, the following notice accompanied
* the original version of this file:
*
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
* *
* The Original Code is the Elliptic Curve Cryptography library. * The Original Code is the Elliptic Curve Cryptography library.
* *
@ -37,23 +34,7 @@
* Dr Vipul Gupta <vipul.gupta@sun.com> and * Dr Vipul Gupta <vipul.gupta@sun.com> and
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
* *
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
*********************************************************************** */ *********************************************************************** */
/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*/
#include "mplogic.h" #include "mplogic.h"
#include "ec.h" #include "ec.h"

View File

@ -1,30 +1,27 @@
/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* ********************************************************************* /* *********************************************************************
*
* Sun elects to have this file available under and governed by the
* Mozilla Public License Version 1.1 ("MPL") (see
* http://www.mozilla.org/MPL/ for full license text). For the avoidance
* of doubt and subject to the following, Sun also elects to allow
* licensees to use this file under the MPL, the GNU General Public
* License version 2 only or the Lesser General Public License version
* 2.1 only. Any references to the "GNU General Public License version 2
* or later" or "GPL" in the following shall be construed to mean the
* GNU General Public License version 2 only. Any references to the "GNU
* Lesser General Public License version 2.1 or later" or "LGPL" in the
* following shall be construed to mean the GNU Lesser General Public
* License version 2.1 only. However, the following notice accompanied
* the original version of this file:
*
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
* *
* The Original Code is the Elliptic Curve Cryptography library. * The Original Code is the Elliptic Curve Cryptography library.
* *
@ -36,23 +33,7 @@
* Contributor(s): * Contributor(s):
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
* *
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
*********************************************************************** */ *********************************************************************** */
/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*/
#ifndef __ec_h_ #ifndef __ec_h_
#define __ec_h_ #define __ec_h_

View File

@ -1,30 +1,27 @@
/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* ********************************************************************* /* *********************************************************************
*
* Sun elects to have this file available under and governed by the
* Mozilla Public License Version 1.1 ("MPL") (see
* http://www.mozilla.org/MPL/ for full license text). For the avoidance
* of doubt and subject to the following, Sun also elects to allow
* licensees to use this file under the MPL, the GNU General Public
* License version 2 only or the Lesser General Public License version
* 2.1 only. Any references to the "GNU General Public License version 2
* or later" or "GPL" in the following shall be construed to mean the
* GNU General Public License version 2 only. Any references to the "GNU
* Lesser General Public License version 2.1 or later" or "LGPL" in the
* following shall be construed to mean the GNU Lesser General Public
* License version 2.1 only. However, the following notice accompanied
* the original version of this file:
*
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
* *
* The Original Code is the elliptic curve math library for binary polynomial field curves. * The Original Code is the elliptic curve math library for binary polynomial field curves.
* *
@ -36,23 +33,7 @@
* Contributor(s): * Contributor(s):
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
* *
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
*********************************************************************** */ *********************************************************************** */
/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _EC2_H #ifndef _EC2_H
#define _EC2_H #define _EC2_H

View File

@ -1,30 +1,27 @@
/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* ********************************************************************* /* *********************************************************************
*
* Sun elects to have this file available under and governed by the
* Mozilla Public License Version 1.1 ("MPL") (see
* http://www.mozilla.org/MPL/ for full license text). For the avoidance
* of doubt and subject to the following, Sun also elects to allow
* licensees to use this file under the MPL, the GNU General Public
* License version 2 only or the Lesser General Public License version
* 2.1 only. Any references to the "GNU General Public License version 2
* or later" or "GPL" in the following shall be construed to mean the
* GNU General Public License version 2 only. Any references to the "GNU
* Lesser General Public License version 2.1 or later" or "LGPL" in the
* following shall be construed to mean the GNU Lesser General Public
* License version 2.1 only. However, the following notice accompanied
* the original version of this file:
*
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
* *
* The Original Code is the elliptic curve math library for binary polynomial field curves. * The Original Code is the elliptic curve math library for binary polynomial field curves.
* *
@ -38,23 +35,7 @@
* Stephen Fung <fungstep@hotmail.com>, and * Stephen Fung <fungstep@hotmail.com>, and
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories. * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
* *
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
*********************************************************************** */ *********************************************************************** */
/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*/
#include "ec2.h" #include "ec2.h"
#include "mp_gf2m.h" #include "mp_gf2m.h"

View File

@ -1,30 +1,27 @@
/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* ********************************************************************* /* *********************************************************************
*
* Sun elects to have this file available under and governed by the
* Mozilla Public License Version 1.1 ("MPL") (see
* http://www.mozilla.org/MPL/ for full license text). For the avoidance
* of doubt and subject to the following, Sun also elects to allow
* licensees to use this file under the MPL, the GNU General Public
* License version 2 only or the Lesser General Public License version
* 2.1 only. Any references to the "GNU General Public License version 2
* or later" or "GPL" in the following shall be construed to mean the
* GNU General Public License version 2 only. Any references to the "GNU
* Lesser General Public License version 2.1 or later" or "LGPL" in the
* following shall be construed to mean the GNU Lesser General Public
* License version 2.1 only. However, the following notice accompanied
* the original version of this file:
*
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
* *
* The Original Code is the elliptic curve math library for binary polynomial field curves. * The Original Code is the elliptic curve math library for binary polynomial field curves.
* *
@ -38,23 +35,7 @@
* Stephen Fung <fungstep@hotmail.com>, and * Stephen Fung <fungstep@hotmail.com>, and
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories. * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
* *
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
*********************************************************************** */ *********************************************************************** */
/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*/
#include "ec2.h" #include "ec2.h"
#include "mp_gf2m.h" #include "mp_gf2m.h"

View File

@ -1,30 +1,27 @@
/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* ********************************************************************* /* *********************************************************************
*
* Sun elects to have this file available under and governed by the
* Mozilla Public License Version 1.1 ("MPL") (see
* http://www.mozilla.org/MPL/ for full license text). For the avoidance
* of doubt and subject to the following, Sun also elects to allow
* licensees to use this file under the MPL, the GNU General Public
* License version 2 only or the Lesser General Public License version
* 2.1 only. Any references to the "GNU General Public License version 2
* or later" or "GPL" in the following shall be construed to mean the
* GNU General Public License version 2 only. Any references to the "GNU
* Lesser General Public License version 2.1 or later" or "LGPL" in the
* following shall be construed to mean the GNU Lesser General Public
* License version 2.1 only. However, the following notice accompanied
* the original version of this file:
*
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
* *
* The Original Code is the elliptic curve math library for binary polynomial field curves. * The Original Code is the elliptic curve math library for binary polynomial field curves.
* *
@ -38,23 +35,7 @@
* Stephen Fung <fungstep@hotmail.com>, and * Stephen Fung <fungstep@hotmail.com>, and
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories. * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
* *
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
*********************************************************************** */ *********************************************************************** */
/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*/
#include "ec2.h" #include "ec2.h"
#include "mp_gf2m.h" #include "mp_gf2m.h"

View File

@ -1,30 +1,27 @@
/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* ********************************************************************* /* *********************************************************************
*
* Sun elects to have this file available under and governed by the
* Mozilla Public License Version 1.1 ("MPL") (see
* http://www.mozilla.org/MPL/ for full license text). For the avoidance
* of doubt and subject to the following, Sun also elects to allow
* licensees to use this file under the MPL, the GNU General Public
* License version 2 only or the Lesser General Public License version
* 2.1 only. Any references to the "GNU General Public License version 2
* or later" or "GPL" in the following shall be construed to mean the
* GNU General Public License version 2 only. Any references to the "GNU
* Lesser General Public License version 2.1 or later" or "LGPL" in the
* following shall be construed to mean the GNU Lesser General Public
* License version 2.1 only. However, the following notice accompanied
* the original version of this file:
*
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
* *
* The Original Code is the elliptic curve math library for binary polynomial field curves. * The Original Code is the elliptic curve math library for binary polynomial field curves.
* *
@ -36,23 +33,7 @@
* Contributor(s): * Contributor(s):
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
* *
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
*********************************************************************** */ *********************************************************************** */
/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*/
#include "ec2.h" #include "ec2.h"
#include "mplogic.h" #include "mplogic.h"

View File

@ -1,30 +1,27 @@
/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* ********************************************************************* /* *********************************************************************
*
* Sun elects to have this file available under and governed by the
* Mozilla Public License Version 1.1 ("MPL") (see
* http://www.mozilla.org/MPL/ for full license text). For the avoidance
* of doubt and subject to the following, Sun also elects to allow
* licensees to use this file under the MPL, the GNU General Public
* License version 2 only or the Lesser General Public License version
* 2.1 only. Any references to the "GNU General Public License version 2
* or later" or "GPL" in the following shall be construed to mean the
* GNU General Public License version 2 only. Any references to the "GNU
* Lesser General Public License version 2.1 or later" or "LGPL" in the
* following shall be construed to mean the GNU Lesser General Public
* License version 2.1 only. However, the following notice accompanied
* the original version of this file:
*
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
* *
* The Original Code is the elliptic curve math library for binary polynomial field curves. * The Original Code is the elliptic curve math library for binary polynomial field curves.
* *
@ -38,23 +35,7 @@
* Stephen Fung <fungstep@hotmail.com>, and * Stephen Fung <fungstep@hotmail.com>, and
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories. * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
* *
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
*********************************************************************** */ *********************************************************************** */
/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*/
#include "ec2.h" #include "ec2.h"
#include "mplogic.h" #include "mplogic.h"

View File

@ -1,30 +1,27 @@
/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* ********************************************************************* /* *********************************************************************
*
* Sun elects to have this file available under and governed by the
* Mozilla Public License Version 1.1 ("MPL") (see
* http://www.mozilla.org/MPL/ for full license text). For the avoidance
* of doubt and subject to the following, Sun also elects to allow
* licensees to use this file under the MPL, the GNU General Public
* License version 2 only or the Lesser General Public License version
* 2.1 only. Any references to the "GNU General Public License version 2
* or later" or "GPL" in the following shall be construed to mean the
* GNU General Public License version 2 only. Any references to the "GNU
* Lesser General Public License version 2.1 or later" or "LGPL" in the
* following shall be construed to mean the GNU Lesser General Public
* License version 2.1 only. However, the following notice accompanied
* the original version of this file:
*
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
* *
* The Original Code is the elliptic curve math library. * The Original Code is the elliptic curve math library.
* *
@ -36,23 +33,7 @@
* Contributor(s): * Contributor(s):
* Stephen Fung <fungstep@hotmail.com>, Sun Microsystems Laboratories * Stephen Fung <fungstep@hotmail.com>, Sun Microsystems Laboratories
* *
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
*********************************************************************** */ *********************************************************************** */
/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*/
#include "ecl-priv.h" #include "ecl-priv.h"

View File

@ -1,30 +1,27 @@
/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* ********************************************************************* /* *********************************************************************
*
* Sun elects to have this file available under and governed by the
* Mozilla Public License Version 1.1 ("MPL") (see
* http://www.mozilla.org/MPL/ for full license text). For the avoidance
* of doubt and subject to the following, Sun also elects to allow
* licensees to use this file under the MPL, the GNU General Public
* License version 2 only or the Lesser General Public License version
* 2.1 only. Any references to the "GNU General Public License version 2
* or later" or "GPL" in the following shall be construed to mean the
* GNU General Public License version 2 only. Any references to the "GNU
* Lesser General Public License version 2.1 or later" or "LGPL" in the
* following shall be construed to mean the GNU Lesser General Public
* License version 2.1 only. However, the following notice accompanied
* the original version of this file:
*
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
* *
* The Original Code is the Netscape security libraries. * The Original Code is the Netscape security libraries.
* *
@ -37,23 +34,7 @@
* Dr Vipul Gupta <vipul.gupta@sun.com> and * Dr Vipul Gupta <vipul.gupta@sun.com> and
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
* *
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
*********************************************************************** */ *********************************************************************** */
/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _ECC_IMPL_H #ifndef _ECC_IMPL_H
#define _ECC_IMPL_H #define _ECC_IMPL_H

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