提交 0bdca130 编写于 作者: L lana

Merge

...@@ -91,3 +91,5 @@ b53f226b1d91473ac54184afa827be07b87e0319 jdk7-b112 ...@@ -91,3 +91,5 @@ b53f226b1d91473ac54184afa827be07b87e0319 jdk7-b112
e250cef36ea05e627e7e6f7d75e5e19f529e2ba3 jdk7-b114 e250cef36ea05e627e7e6f7d75e5e19f529e2ba3 jdk7-b114
449bad8d67b5808ecf0f927683acc0a5940f8c85 jdk7-b115 449bad8d67b5808ecf0f927683acc0a5940f8c85 jdk7-b115
1657ed4e1d86c8aa2028ab5a41f9da1ac4a369f8 jdk7-b116 1657ed4e1d86c8aa2028ab5a41f9da1ac4a369f8 jdk7-b116
3e6726bbf80a4254ecd01051c8ed77ee19325e46 jdk7-b117
b357910aa04aead2a16b6d6ff395a8df4b51d1dd jdk7-b118
...@@ -413,6 +413,7 @@ JAVA_JAVA_java = \ ...@@ -413,6 +413,7 @@ JAVA_JAVA_java = \
java/io/FilePermission.java \ java/io/FilePermission.java \
java/io/Serializable.java \ java/io/Serializable.java \
java/io/Externalizable.java \ java/io/Externalizable.java \
java/io/SerialCallbackContext.java \
java/io/Bits.java \ java/io/Bits.java \
java/io/ObjectInput.java \ java/io/ObjectInput.java \
java/io/ObjectInputStream.java \ java/io/ObjectInputStream.java \
......
...@@ -148,14 +148,9 @@ include $(BUILDDIR)/common/Library.gmk ...@@ -148,14 +148,9 @@ include $(BUILDDIR)/common/Library.gmk
# #
ifeq ($(PLATFORM), windows) ifeq ($(PLATFORM), windows)
STATIC_LIBRARY_DIR = $(OBJDIR)/static STATIC_LIBRARY = $(OBJDIR)/static/$(LIBPREFIX)$(LIBRARY).lib
STATIC_LIBRARY_NAME = $(LIBPREFIX)$(LIBRARY).lib
STATIC_LIBRARY = $(STATIC_LIBRARY_DIR)/$(STATIC_LIBRARY_NAME)
$(STATIC_LIBRARY_DIR): $(OBJDIR) $(STATIC_LIBRARY): $(FILES_o)
@$(MKDIR) $(STATIC_LIBRARY_DIR)
$(STATIC_LIBRARY): $(STATIC_LIBRARY_DIR)
@$(prep-target) @$(prep-target)
$(LIBEXE) -nologo -out:$@ $(FILES_o) $(LIBEXE) -nologo -out:$@ $(FILES_o)
......
...@@ -33,7 +33,6 @@ FILES_src = \ ...@@ -33,7 +33,6 @@ FILES_src = \
java/nio/channels/AsynchronousByteChannel.java \ java/nio/channels/AsynchronousByteChannel.java \
java/nio/channels/AsynchronousChannel.java \ java/nio/channels/AsynchronousChannel.java \
java/nio/channels/AsynchronousChannelGroup.java \ java/nio/channels/AsynchronousChannelGroup.java \
java/nio/channels/AsynchronousDatagramChannel.java \
java/nio/channels/AsynchronousFileChannel.java \ java/nio/channels/AsynchronousFileChannel.java \
java/nio/channels/AsynchronousServerSocketChannel.java \ java/nio/channels/AsynchronousServerSocketChannel.java \
java/nio/channels/AsynchronousSocketChannel.java \ java/nio/channels/AsynchronousSocketChannel.java \
...@@ -207,7 +206,6 @@ FILES_src = \ ...@@ -207,7 +206,6 @@ FILES_src = \
sun/nio/ch/SelChImpl.java \ sun/nio/ch/SelChImpl.java \
sun/nio/ch/ServerSocketAdaptor.java \ sun/nio/ch/ServerSocketAdaptor.java \
sun/nio/ch/ServerSocketChannelImpl.java \ sun/nio/ch/ServerSocketChannelImpl.java \
sun/nio/ch/SimpleAsynchronousDatagramChannelImpl.java \
sun/nio/ch/SinkChannelImpl.java \ sun/nio/ch/SinkChannelImpl.java \
sun/nio/ch/SocketAdaptor.java \ sun/nio/ch/SocketAdaptor.java \
sun/nio/ch/SocketChannelImpl.java \ sun/nio/ch/SocketChannelImpl.java \
......
...@@ -53,7 +53,7 @@ FILES_export = \ ...@@ -53,7 +53,7 @@ FILES_export = \
# #
# Extra cc/linker flags. # Extra cc/linker flags.
# #
LDLIBS += dsound.lib winmm.lib user32.lib LDLIBS += dsound.lib winmm.lib user32.lib ole32.lib
CPPFLAGS += \ CPPFLAGS += \
-DUSE_DAUDIO=TRUE \ -DUSE_DAUDIO=TRUE \
-I$(SHARE_SRC)/native/com/sun/media/sound \ -I$(SHARE_SRC)/native/com/sun/media/sound \
......
...@@ -48,8 +48,8 @@ jar.jmx.name = jmx.jar ...@@ -48,8 +48,8 @@ jar.jmx.name = jmx.jar
jar.jmx.sealed = true jar.jmx.sealed = true
jar.jmx.spec.title = JSR 003, 160, 255 - JMX API jar.jmx.spec.title = JSR 003, 160, 255 - JMX API
jar.jmx.spec.version = ${project.spec.version} jar.jmx.spec.version = ${project.spec.version}
jar.jmx.spec.vendor = Sun Microsystems, Inc. jar.jmx.spec.vendor = Oracle Corporation
jar.jmx.impl.title = JSR 003, 160, 255 - OpenJDK 7 JMX API jar.jmx.impl.title = JSR 003, 160, 255 - OpenJDK 7 JMX API
jar.jmx.impl.vendor = Project OpenJDK jar.jmx.impl.vendor = Project OpenJDK
javadoc.options=-J-Xmx256m javadoc.options=-J-Xmx256m
...@@ -21,4 +21,4 @@ ...@@ -21,4 +21,4 @@
# or visit www.oracle.com if you need additional information or have any # or visit www.oracle.com if you need additional information or have any
# questions. # questions.
# #
tzdata2010l tzdata2010o
...@@ -569,8 +569,8 @@ Rule HK 1953 only - Nov 1 3:30 0 - ...@@ -569,8 +569,8 @@ Rule HK 1953 only - Nov 1 3:30 0 -
Rule HK 1954 1964 - Mar Sun>=18 3:30 1:00 S Rule HK 1954 1964 - Mar Sun>=18 3:30 1:00 S
Rule HK 1954 only - Oct 31 3:30 0 - Rule HK 1954 only - Oct 31 3:30 0 -
Rule HK 1955 1964 - Nov Sun>=1 3:30 0 - Rule HK 1955 1964 - Nov Sun>=1 3:30 0 -
Rule HK 1965 1977 - Apr Sun>=16 3:30 1:00 S Rule HK 1965 1976 - Apr Sun>=16 3:30 1:00 S
Rule HK 1965 1977 - Oct Sun>=16 3:30 0 - Rule HK 1965 1976 - Oct Sun>=16 3:30 0 -
Rule HK 1973 only - Dec 30 3:30 1:00 S Rule HK 1973 only - Dec 30 3:30 1:00 S
Rule HK 1979 only - May Sun>=8 3:30 1:00 S Rule HK 1979 only - May Sun>=8 3:30 1:00 S
Rule HK 1979 only - Oct Sun>=16 3:30 0 - Rule HK 1979 only - Oct Sun>=16 3:30 0 -
......
...@@ -306,13 +306,26 @@ Zone Indian/Cocos 6:27:40 - LMT 1900 ...@@ -306,13 +306,26 @@ Zone Indian/Cocos 6:27:40 - LMT 1900
# http://www.timeanddate.com/news/time/fiji-dst-ends-march-2010.html # http://www.timeanddate.com/news/time/fiji-dst-ends-march-2010.html
# </a> # </a>
# From Alexander Krivenyshev (2010-10-24):
# According to Radio Fiji and Fiji Times online, Fiji will end DST 3
# weeks earlier than expected - on March 6, 2011, not March 27, 2011...
# Here is confirmation from Government of the Republic of the Fiji Islands,
# Ministry of Information (fiji.gov.fj) web site:
# <a href="http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=2608:daylight-savings&catid=71:press-releases&Itemid=155">
# http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=2608:daylight-savings&catid=71:press-releases&Itemid=155
# </a>
# or
# <a href="http://www.worldtimezone.com/dst_news/dst_news_fiji04.html">
# http://www.worldtimezone.com/dst_news/dst_news_fiji04.html
# </a>
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Fiji 1998 1999 - Nov Sun>=1 2:00 1:00 S Rule Fiji 1998 1999 - Nov Sun>=1 2:00 1:00 S
Rule Fiji 1999 2000 - Feb lastSun 3:00 0 - Rule Fiji 1999 2000 - Feb lastSun 3:00 0 -
Rule Fiji 2009 only - Nov 29 2:00 1:00 S Rule Fiji 2009 only - Nov 29 2:00 1:00 S
Rule Fiji 2010 only - Mar lastSun 3:00 0 - Rule Fiji 2010 only - Mar lastSun 3:00 0 -
Rule Fiji 2010 only - Oct 24 2:00 1:00 S Rule Fiji 2010 only - Oct 24 2:00 1:00 S
Rule Fiji 2011 only - Mar lastSun 3:00 0 - Rule Fiji 2011 only - Mar Sun>=1 3:00 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL] # Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Pacific/Fiji 11:53:40 - LMT 1915 Oct 26 # Suva Zone Pacific/Fiji 11:53:40 - LMT 1915 Oct 26 # Suva
12:00 Fiji FJ%sT # Fiji Time 12:00 Fiji FJ%sT # Fiji Time
...@@ -509,11 +522,21 @@ Zone Pacific/Pago_Pago 12:37:12 - LMT 1879 Jul 5 ...@@ -509,11 +522,21 @@ Zone Pacific/Pago_Pago 12:37:12 - LMT 1879 Jul 5
# http://www.parliament.gov.ws/documents/acts/Daylight%20Saving%20Act%20%202009%20%28English%29%20-%20Final%207-7-091.pdf # http://www.parliament.gov.ws/documents/acts/Daylight%20Saving%20Act%20%202009%20%28English%29%20-%20Final%207-7-091.pdf
# </a> # </a>
# From Raymond Hughes (2010-10-07):
# Please see
# <a href="http://www.mcil.gov.ws">
# http://www.mcil.gov.ws
# </a>,
# the Ministry of Commerce, Industry and Labour (sideframe) "Last Sunday
# September 2010 (26/09/10) - adjust clocks forward from 12:00 midnight
# to 01:00am and First Sunday April 2011 (03/04/11) - adjust clocks
# backwards from 1:00am to 12:00am"
Zone Pacific/Apia 12:33:04 - LMT 1879 Jul 5 Zone Pacific/Apia 12:33:04 - LMT 1879 Jul 5
-11:26:56 - LMT 1911 -11:26:56 - LMT 1911
-11:30 - SAMT 1950 # Samoa Time -11:30 - SAMT 1950 # Samoa Time
-11:00 - WST 2010 Sep 26 -11:00 - WST 2010 Sep 26
-11:00 1:00 WSDT 2011 Apr 3 -11:00 1:00 WSDT 2011 Apr 3 1:00
-11:00 - WST -11:00 - WST
# Solomon Is # Solomon Is
......
...@@ -63,7 +63,7 @@ AQ -6448-06406 Antarctica/Palmer Palmer Station, Anvers Island ...@@ -63,7 +63,7 @@ AQ -6448-06406 Antarctica/Palmer Palmer Station, Anvers Island
AQ -6736+06253 Antarctica/Mawson Mawson Station, Holme Bay AQ -6736+06253 Antarctica/Mawson Mawson Station, Holme Bay
AQ -6835+07758 Antarctica/Davis Davis Station, Vestfold Hills AQ -6835+07758 Antarctica/Davis Davis Station, Vestfold Hills
AQ -6617+11031 Antarctica/Casey Casey Station, Bailey Peninsula AQ -6617+11031 Antarctica/Casey Casey Station, Bailey Peninsula
AQ -7824+10654 Antarctica/Vostok Vostok Station, S Magnetic Pole AQ -7824+10654 Antarctica/Vostok Vostok Station, Lake Vostok
AQ -6640+14001 Antarctica/DumontDUrville Dumont-d'Urville Station, Terre Adelie AQ -6640+14001 Antarctica/DumontDUrville Dumont-d'Urville Station, Terre Adelie
AQ -690022+0393524 Antarctica/Syowa Syowa Station, E Ongul I AQ -690022+0393524 Antarctica/Syowa Syowa Station, E Ongul I
AQ -5430+15857 Antarctica/Macquarie Macquarie Island Station, Macquarie Island AQ -5430+15857 Antarctica/Macquarie Macquarie Island Station, Macquarie Island
......
...@@ -355,7 +355,6 @@ JavaMain(void * _args) ...@@ -355,7 +355,6 @@ JavaMain(void * _args)
JavaVM *vm = 0; JavaVM *vm = 0;
JNIEnv *env = 0; JNIEnv *env = 0;
jstring mainClassName;
jclass mainClass; jclass mainClass;
jmethodID mainID; jmethodID mainID;
jobjectArray mainArgs; jobjectArray mainArgs;
......
...@@ -72,7 +72,7 @@ inflate_file(int fd, zentry *entry, int *size_out) ...@@ -72,7 +72,7 @@ inflate_file(int fd, zentry *entry, int *size_out)
if (entry->how == STORED) { if (entry->how == STORED) {
*(char *)((size_t)in + entry->csize) = '\0'; *(char *)((size_t)in + entry->csize) = '\0';
if (size_out) { if (size_out) {
*size_out = entry->csize; *size_out = (int)entry->csize;
} }
return (in); return (in);
} else if (entry->how == DEFLATED) { } else if (entry->how == DEFLATED) {
...@@ -103,7 +103,7 @@ inflate_file(int fd, zentry *entry, int *size_out) ...@@ -103,7 +103,7 @@ inflate_file(int fd, zentry *entry, int *size_out)
return (NULL); return (NULL);
} }
if (size_out) { if (size_out) {
*size_out = entry->isize; *size_out = (int)entry->isize;
} }
return (out); return (out);
} else } else
...@@ -317,7 +317,7 @@ find_file(int fd, zentry *entry, const char *file_name) ...@@ -317,7 +317,7 @@ find_file(int fd, zentry *entry, const char *file_name)
* manifest. If so, build the entry record from the data found in * manifest. If so, build the entry record from the data found in
* the header located and return success. * the header located and return success.
*/ */
if (CENNAM(p) == JLI_StrLen(file_name) && if ((size_t)CENNAM(p) == JLI_StrLen(file_name) &&
memcmp((p + CENHDR), file_name, JLI_StrLen(file_name)) == 0) { memcmp((p + CENHDR), file_name, JLI_StrLen(file_name)) == 0) {
if (lseek(fd, base_offset + CENOFF(p), SEEK_SET) < (off_t)0) { if (lseek(fd, base_offset + CENOFF(p), SEEK_SET) < (off_t)0) {
free(buffer); free(buffer);
...@@ -606,8 +606,5 @@ JLI_ManifestIterate(const char *jarfile, attribute_closure ac, void *user_data) ...@@ -606,8 +606,5 @@ JLI_ManifestIterate(const char *jarfile, attribute_closure ac, void *user_data)
} }
free(mp); free(mp);
close(fd); close(fd);
if (rc == 0) return (rc == 0) ? 0 : -2;
return (0);
else
return (-2);
} }
...@@ -290,12 +290,12 @@ FileList_join(FileList fl, char sep) ...@@ -290,12 +290,12 @@ FileList_join(FileList fl, char sep)
char *path; char *path;
char *p; char *p;
for (i = 0, size = 1; i < fl->size; i++) for (i = 0, size = 1; i < fl->size; i++)
size += JLI_StrLen(fl->files[i]) + 1; size += (int)JLI_StrLen(fl->files[i]) + 1;
path = JLI_MemAlloc(size); path = JLI_MemAlloc(size);
for (i = 0, p = path; i < fl->size; i++) { for (i = 0, p = path; i < fl->size; i++) {
int len = JLI_StrLen(fl->files[i]); int len = (int)JLI_StrLen(fl->files[i]);
if (i > 0) *p++ = sep; if (i > 0) *p++ = sep;
memcpy(p, fl->files[i], len); memcpy(p, fl->files[i], len);
p += len; p += len;
...@@ -309,7 +309,7 @@ static FileList ...@@ -309,7 +309,7 @@ static FileList
FileList_split(const char *path, char sep) FileList_split(const char *path, char sep)
{ {
const char *p, *q; const char *p, *q;
int len = JLI_StrLen(path); int len = (int)JLI_StrLen(path);
int count; int count;
FileList fl; FileList fl;
for (count = 1, p = path; p < path + len; p++) for (count = 1, p = path; p < path + len; p++)
...@@ -330,7 +330,7 @@ FileList_split(const char *path, char sep) ...@@ -330,7 +330,7 @@ FileList_split(const char *path, char sep)
static int static int
isJarFileName(const char *filename) isJarFileName(const char *filename)
{ {
int len = JLI_StrLen(filename); int len = (int)JLI_StrLen(filename);
return (len >= 4) && return (len >= 4) &&
(filename[len - 4] == '.') && (filename[len - 4] == '.') &&
(equal(filename + len - 3, "jar") || (equal(filename + len - 3, "jar") ||
...@@ -342,8 +342,8 @@ isJarFileName(const char *filename) ...@@ -342,8 +342,8 @@ isJarFileName(const char *filename)
static char * static char *
wildcardConcat(const char *wildcard, const char *basename) wildcardConcat(const char *wildcard, const char *basename)
{ {
int wildlen = JLI_StrLen(wildcard); int wildlen = (int)JLI_StrLen(wildcard);
int baselen = JLI_StrLen(basename); int baselen = (int)JLI_StrLen(basename);
char *filename = (char *) JLI_MemAlloc(wildlen + baselen); char *filename = (char *) JLI_MemAlloc(wildlen + baselen);
/* Replace the trailing '*' with basename */ /* Replace the trailing '*' with basename */
memcpy(filename, wildcard, wildlen-1); memcpy(filename, wildcard, wildlen-1);
...@@ -369,7 +369,7 @@ wildcardFileList(const char *wildcard) ...@@ -369,7 +369,7 @@ wildcardFileList(const char *wildcard)
static int static int
isWildcard(const char *filename) isWildcard(const char *filename)
{ {
int len = JLI_StrLen(filename); int len = (int)JLI_StrLen(filename);
return (len > 0) && return (len > 0) &&
(filename[len - 1] == '*') && (filename[len - 1] == '*') &&
(len == 1 || IS_FILE_SEPARATOR(filename[len - 2])) && (len == 1 || IS_FILE_SEPARATOR(filename[len - 2])) &&
......
/* /*
* Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 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
...@@ -253,7 +253,8 @@ final class AESCrypt extends SymmetricCipher implements AESConstants ...@@ -253,7 +253,8 @@ final class AESCrypt extends SymmetricCipher implements AESConstants
for (j = 0; j < 8; j++) { for (j = 0; j < 8; j++) {
if (AA[i][j] != 0) { if (AA[i][j] != 0) {
AA[i][j] = (byte) AA[i][j] = (byte)
alog[(255 + log[AA[i][j] & 0xFF] - log[pivot & 0xFF]) % 255]; alog[(255 + log[AA[i][j] & 0xFF] - log[pivot & 0xFF])
% 255];
} }
} }
for (t = 0; t < 4; t++) { for (t = 0; t < 4; t++) {
......
/* /*
* Copyright (c) 2003, 2009, 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
...@@ -92,7 +92,8 @@ public final class ARCFOURCipher extends CipherSpi { ...@@ -92,7 +92,8 @@ public final class ARCFOURCipher extends CipherSpi {
} }
// core crypt code. OFB style, so works for both encryption and decryption // core crypt code. OFB style, so works for both encryption and decryption
private void crypt(byte[] in, int inOfs, int inLen, byte[] out, int outOfs) { private void crypt(byte[] in, int inOfs, int inLen, byte[] out,
int outOfs) {
if (is < 0) { if (is < 0) {
// doFinal() was called, need to reset the cipher to initial state // doFinal() was called, need to reset the cipher to initial state
init(lastKey); init(lastKey);
......
/* /*
* Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 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
...@@ -31,8 +31,8 @@ import javax.crypto.*; ...@@ -31,8 +31,8 @@ import javax.crypto.*;
import javax.crypto.spec.*; import javax.crypto.spec.*;
/** /**
* This class implements the DESede algorithm (DES-EDE, tripleDES) in its various * This class implements the DESede algorithm (DES-EDE, tripleDES) in
* modes (<code>ECB</code>, <code>CFB</code>, <code>OFB</code>, * its various modes (<code>ECB</code>, <code>CFB</code>, <code>OFB</code>,
* <code>CBC</code>, <code>PCBC</code>) and padding schemes * <code>CBC</code>, <code>PCBC</code>) and padding schemes
* (<code>PKCS5Padding</code>, <code>NoPadding</code>, * (<code>PKCS5Padding</code>, <code>NoPadding</code>,
* <code>ISO10126Padding</code>). * <code>ISO10126Padding</code>).
......
/* /*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 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
...@@ -190,7 +190,8 @@ javax.crypto.interfaces.DHPrivateKey, Serializable { ...@@ -190,7 +190,8 @@ javax.crypto.interfaces.DHPrivateKey, Serializable {
ike.initCause(e); ike.initCause(e);
throw ike; throw ike;
} catch (IOException e) { } catch (IOException e) {
InvalidKeyException ike = new InvalidKeyException("Error parsing key encoding: " + e.getMessage()); InvalidKeyException ike = new InvalidKeyException(
"Error parsing key encoding: " + e.getMessage());
ike.initCause(e); ike.initCause(e);
throw ike; throw ike;
} }
...@@ -300,7 +301,8 @@ javax.crypto.interfaces.DHPrivateKey, Serializable { ...@@ -300,7 +301,8 @@ javax.crypto.interfaces.DHPrivateKey, Serializable {
DerInputStream in = new DerInputStream(this.key); DerInputStream in = new DerInputStream(this.key);
this.x = in.getBigInteger(); this.x = in.getBigInteger();
} catch (IOException e) { } catch (IOException e) {
InvalidKeyException ike = new InvalidKeyException("Error parsing key encoding: " + e.getMessage()); InvalidKeyException ike = new InvalidKeyException(
"Error parsing key encoding: " + e.getMessage());
ike.initCause(e); ike.initCause(e);
throw ike; throw ike;
} }
......
/* /*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 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
...@@ -180,7 +180,8 @@ javax.crypto.interfaces.DHPublicKey, Serializable { ...@@ -180,7 +180,8 @@ javax.crypto.interfaces.DHPublicKey, Serializable {
throw new InvalidKeyException("Private-value length too big"); throw new InvalidKeyException("Private-value length too big");
} catch (IOException e) { } catch (IOException e) {
throw new InvalidKeyException("Error parsing key encoding: " + e.toString()); throw new InvalidKeyException(
"Error parsing key encoding: " + e.toString());
} }
} }
...@@ -281,7 +282,8 @@ javax.crypto.interfaces.DHPublicKey, Serializable { ...@@ -281,7 +282,8 @@ javax.crypto.interfaces.DHPublicKey, Serializable {
DerInputStream in = new DerInputStream(this.key); DerInputStream in = new DerInputStream(this.key);
this.y = in.getBigInteger(); this.y = in.getBigInteger();
} catch (IOException e) { } catch (IOException e) {
throw new InvalidKeyException("Error parsing key encoding: " + e.toString()); throw new InvalidKeyException(
"Error parsing key encoding: " + e.toString());
} }
} }
......
/* /*
* Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 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
...@@ -764,7 +764,8 @@ public final class JceKeyStore extends KeyStoreSpi { ...@@ -764,7 +764,8 @@ public final class JceKeyStore extends KeyStoreSpi {
cf = (CertificateFactory)cfs.get(certType); cf = (CertificateFactory)cfs.get(certType);
} else { } else {
// create new certificate factory // create new certificate factory
cf = CertificateFactory.getInstance(certType); cf = CertificateFactory.getInstance(
certType);
// store the certificate factory so we can // store the certificate factory so we can
// reuse it later // reuse it later
cfs.put(certType, cf); cfs.put(certType, cf);
...@@ -863,8 +864,9 @@ public final class JceKeyStore extends KeyStoreSpi { ...@@ -863,8 +864,9 @@ public final class JceKeyStore extends KeyStoreSpi {
dis.readFully(actual); dis.readFully(actual);
for (int i = 0; i < computed.length; i++) { for (int i = 0; i < computed.length; i++) {
if (computed[i] != actual[i]) { if (computed[i] != actual[i]) {
throw new IOException("Keystore was tampered with, or " throw new IOException(
+ "password was incorrect"); "Keystore was tampered with, or "
+ "password was incorrect");
} }
} }
} }
......
/* /*
* Copyright (c) 2003, 2007, 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
...@@ -139,7 +139,8 @@ public final class OAEPParameters extends AlgorithmParametersSpi { ...@@ -139,7 +139,8 @@ public final class OAEPParameters extends AlgorithmParametersSpi {
if (!val.getOID().equals((Object) OID_MGF1)) { if (!val.getOID().equals((Object) OID_MGF1)) {
throw new IOException("Only MGF1 mgf is supported"); throw new IOException("Only MGF1 mgf is supported");
} }
AlgorithmId params = AlgorithmId.parse(new DerValue(val.getEncodedParams())); AlgorithmId params = AlgorithmId.parse(
new DerValue(val.getEncodedParams()));
String mgfDigestName = convertToStandardName(params.getName()); String mgfDigestName = convertToStandardName(params.getName());
if (mgfDigestName.equals("SHA-1")) { if (mgfDigestName.equals("SHA-1")) {
mgfSpec = MGF1ParameterSpec.SHA1; mgfSpec = MGF1ParameterSpec.SHA1;
...@@ -150,7 +151,8 @@ public final class OAEPParameters extends AlgorithmParametersSpi { ...@@ -150,7 +151,8 @@ public final class OAEPParameters extends AlgorithmParametersSpi {
} else if (mgfDigestName.equals("SHA-512")) { } else if (mgfDigestName.equals("SHA-512")) {
mgfSpec = MGF1ParameterSpec.SHA512; mgfSpec = MGF1ParameterSpec.SHA512;
} else { } else {
throw new IOException("Unrecognized message digest algorithm"); throw new IOException(
"Unrecognized message digest algorithm");
} }
} else if (data.isContextSpecific((byte) 0x02)) { } else if (data.isContextSpecific((byte) 0x02)) {
// pSource algid // pSource algid
......
/* /*
* Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 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
...@@ -121,8 +121,8 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey { ...@@ -121,8 +121,8 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey {
this.key = deriveKey(prf, passwdBytes, salt, iterCount, keyLength); this.key = deriveKey(prf, passwdBytes, salt, iterCount, keyLength);
} }
private static byte[] deriveKey(final Mac prf, final byte[] password, byte[] salt, private static byte[] deriveKey(final Mac prf, final byte[] password,
int iterCount, int keyLengthInBit) { byte[] salt, int iterCount, int keyLengthInBit) {
int keyLength = keyLengthInBit/8; int keyLength = keyLengthInBit/8;
byte[] key = new byte[keyLength]; byte[] key = new byte[keyLength];
try { try {
...@@ -155,8 +155,9 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey { ...@@ -155,8 +155,9 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey {
if (this == obj) return true; if (this == obj) return true;
if (this.getClass() != obj.getClass()) return false; if (this.getClass() != obj.getClass()) return false;
SecretKey sk = (SecretKey)obj; SecretKey sk = (SecretKey)obj;
return prf.getAlgorithm().equalsIgnoreCase(sk.getAlgorithm()) && return prf.getAlgorithm().equalsIgnoreCase(
Arrays.equals(password, sk.getEncoded()); sk.getAlgorithm()) &&
Arrays.equals(password, sk.getEncoded());
} }
}; };
prf.init(macKey); prf.init(macKey);
......
/* /*
* Copyright (c) 2003, 2009, 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
...@@ -206,7 +206,8 @@ final class PKCS12PBECipherCore { ...@@ -206,7 +206,8 @@ final class PKCS12PBECipherCore {
(algo.equalsIgnoreCase("RC2")?"RC2_40":algo), "SunJCE"); (algo.equalsIgnoreCase("RC2")?"RC2_40":algo), "SunJCE");
} catch (GeneralSecurityException gse) { } catch (GeneralSecurityException gse) {
// should never happen // should never happen
throw new RuntimeException("SunJCE provider is not configured properly"); throw new RuntimeException(
"SunJCE provider is not configured properly");
} }
try { try {
params.init(pbeSpec); params.init(pbeSpec);
...@@ -316,7 +317,8 @@ final class PKCS12PBECipherCore { ...@@ -316,7 +317,8 @@ final class PKCS12PBECipherCore {
try { try {
paramSpec = params.getParameterSpec(PBEParameterSpec.class); paramSpec = params.getParameterSpec(PBEParameterSpec.class);
} catch (InvalidParameterSpecException ipse) { } catch (InvalidParameterSpecException ipse) {
throw new InvalidAlgorithmParameterException("requires PBE parameters"); throw new InvalidAlgorithmParameterException(
"requires PBE parameters");
} }
} }
implInit(opmode, key, paramSpec, random); implInit(opmode, key, paramSpec, random);
......
/* /*
* Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 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
...@@ -423,15 +423,31 @@ public final class SunJCE extends Provider { ...@@ -423,15 +423,31 @@ public final class SunJCE extends Provider {
/* /*
* SSL/TLS mechanisms * SSL/TLS mechanisms
*
* These are strictly internal implementations and may
* be changed at any time. These names were chosen
* because PKCS11/SunPKCS11 does not yet have TLS1.2
* mechanisms, and it will cause calls to come here.
*/ */
put("KeyGenerator.SunTlsPrf", put("KeyGenerator.SunTlsPrf",
"com.sun.crypto.provider.TlsPrfGenerator"); "com.sun.crypto.provider.TlsPrfGenerator$V10");
put("KeyGenerator.SunTlsRsaPremasterSecret", put("KeyGenerator.SunTls12Prf",
"com.sun.crypto.provider.TlsRsaPremasterSecretGenerator"); "com.sun.crypto.provider.TlsPrfGenerator$V12");
put("KeyGenerator.SunTlsMasterSecret", put("KeyGenerator.SunTlsMasterSecret",
"com.sun.crypto.provider.TlsMasterSecretGenerator"); "com.sun.crypto.provider.TlsMasterSecretGenerator");
put("Alg.Alias.KeyGenerator.SunTls12MasterSecret",
"SunTlsMasterSecret");
put("KeyGenerator.SunTlsKeyMaterial", put("KeyGenerator.SunTlsKeyMaterial",
"com.sun.crypto.provider.TlsKeyMaterialGenerator"); "com.sun.crypto.provider.TlsKeyMaterialGenerator");
put("Alg.Alias.KeyGenerator.SunTls12KeyMaterial",
"SunTlsKeyMaterial");
put("KeyGenerator.SunTlsRsaPremasterSecret",
"com.sun.crypto.provider.TlsRsaPremasterSecretGenerator");
put("Alg.Alias.KeyGenerator.SunTls12RsaPremasterSecret",
"SunTlsRsaPremasterSecret");
return null; return null;
} }
......
/* /*
* Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 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
...@@ -65,12 +65,14 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi { ...@@ -65,12 +65,14 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
} }
this.spec = (TlsKeyMaterialParameterSpec)params; this.spec = (TlsKeyMaterialParameterSpec)params;
if ("RAW".equals(spec.getMasterSecret().getFormat()) == false) { if ("RAW".equals(spec.getMasterSecret().getFormat()) == false) {
throw new InvalidAlgorithmParameterException("Key format must be RAW"); throw new InvalidAlgorithmParameterException(
"Key format must be RAW");
} }
protocolVersion = (spec.getMajorVersion() << 8) | spec.getMinorVersion(); protocolVersion = (spec.getMajorVersion() << 8)
if ((protocolVersion < 0x0300) || (protocolVersion > 0x0302)) { | spec.getMinorVersion();
throw new InvalidAlgorithmParameterException if ((protocolVersion < 0x0300) || (protocolVersion > 0x0303)) {
("Only SSL 3.0, TLS 1.0, and TLS 1.1 supported"); throw new InvalidAlgorithmParameterException(
"Only SSL 3.0, TLS 1.0/1.1/1.2 supported");
} }
} }
...@@ -80,8 +82,8 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi { ...@@ -80,8 +82,8 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
protected SecretKey engineGenerateKey() { protected SecretKey engineGenerateKey() {
if (spec == null) { if (spec == null) {
throw new IllegalStateException throw new IllegalStateException(
("TlsKeyMaterialGenerator must be initialized"); "TlsKeyMaterialGenerator must be initialized");
} }
try { try {
return engineGenerateKey0(); return engineGenerateKey0();
...@@ -99,8 +101,8 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi { ...@@ -99,8 +101,8 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
SecretKey clientMacKey = null; SecretKey clientMacKey = null;
SecretKey serverMacKey = null; SecretKey serverMacKey = null;
SecretKey clientCipherKey = null; SecretKey clientCipherKey = null;
IvParameterSpec clientIv = null;
SecretKey serverCipherKey = null; SecretKey serverCipherKey = null;
IvParameterSpec clientIv = null;
IvParameterSpec serverIv = null; IvParameterSpec serverIv = null;
int macLength = spec.getMacKeyLength(); int macLength = spec.getMacKeyLength();
...@@ -109,21 +111,33 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi { ...@@ -109,21 +111,33 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
int keyLength = spec.getCipherKeyLength(); int keyLength = spec.getCipherKeyLength();
int ivLength = spec.getIvLength(); int ivLength = spec.getIvLength();
int keyBlockLen = macLength + keyLength + (isExportable ? 0 : ivLength); int keyBlockLen = macLength + keyLength
+ (isExportable ? 0 : ivLength);
keyBlockLen <<= 1; keyBlockLen <<= 1;
byte[] keyBlock = new byte[keyBlockLen]; byte[] keyBlock = new byte[keyBlockLen];
MessageDigest md5 = MessageDigest.getInstance("MD5"); // These may be used again later for exportable suite calculations.
MessageDigest sha = MessageDigest.getInstance("SHA1"); MessageDigest md5 = null;
MessageDigest sha = null;
// generate key block // generate key block
if (protocolVersion >= 0x0301) { if (protocolVersion >= 0x0303) {
// TLS // TLS 1.2
byte[] seed = concat(serverRandom, clientRandom);
keyBlock = doTLS12PRF(masterSecret, LABEL_KEY_EXPANSION, seed,
keyBlockLen, spec.getPRFHashAlg(),
spec.getPRFHashLength(), spec.getPRFBlockSize());
} else if (protocolVersion >= 0x0301) {
// TLS 1.0/1.1
md5 = MessageDigest.getInstance("MD5");
sha = MessageDigest.getInstance("SHA1");
byte[] seed = concat(serverRandom, clientRandom); byte[] seed = concat(serverRandom, clientRandom);
keyBlock = doPRF(masterSecret, LABEL_KEY_EXPANSION, seed, keyBlock = doTLS10PRF(masterSecret, LABEL_KEY_EXPANSION, seed,
keyBlockLen, md5, sha); keyBlockLen, md5, sha);
} else { } else {
// SSL // SSL
md5 = MessageDigest.getInstance("MD5");
sha = MessageDigest.getInstance("SHA1");
keyBlock = new byte[keyBlockLen]; keyBlock = new byte[keyBlockLen];
byte[] tmp = new byte[20]; byte[] tmp = new byte[20];
...@@ -169,6 +183,7 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi { ...@@ -169,6 +183,7 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
String alg = spec.getCipherAlgorithm(); String alg = spec.getCipherAlgorithm();
// cipher keys
byte[] clientKeyBytes = new byte[keyLength]; byte[] clientKeyBytes = new byte[keyLength];
System.arraycopy(keyBlock, ofs, clientKeyBytes, 0, keyLength); System.arraycopy(keyBlock, ofs, clientKeyBytes, 0, keyLength);
ofs += keyLength; ofs += keyLength;
...@@ -182,6 +197,7 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi { ...@@ -182,6 +197,7 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
clientCipherKey = new SecretKeySpec(clientKeyBytes, alg); clientCipherKey = new SecretKeySpec(clientKeyBytes, alg);
serverCipherKey = new SecretKeySpec(serverKeyBytes, alg); serverCipherKey = new SecretKeySpec(serverKeyBytes, alg);
// IV keys if needed.
if (ivLength != 0) { if (ivLength != 0) {
tmp = new byte[ivLength]; tmp = new byte[ivLength];
...@@ -194,21 +210,28 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi { ...@@ -194,21 +210,28 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
serverIv = new IvParameterSpec(tmp); serverIv = new IvParameterSpec(tmp);
} }
} else { } else {
// if exportable suites, calculate the alternate
// cipher key expansion and IV generation // cipher key expansion and IV generation
if (protocolVersion >= 0x0301) { if (protocolVersion >= 0x0302) {
// TLS 1.1+
throw new RuntimeException(
"Internal Error: TLS 1.1+ should not be negotiating" +
"exportable ciphersuites");
} else if (protocolVersion == 0x0301) {
// TLS 1.0
byte[] seed = concat(clientRandom, serverRandom); byte[] seed = concat(clientRandom, serverRandom);
tmp = doPRF(clientKeyBytes, LABEL_CLIENT_WRITE_KEY, seed, tmp = doTLS10PRF(clientKeyBytes, LABEL_CLIENT_WRITE_KEY, seed,
expandedKeyLength, md5, sha); expandedKeyLength, md5, sha);
clientCipherKey = new SecretKeySpec(tmp, alg); clientCipherKey = new SecretKeySpec(tmp, alg);
tmp = doPRF(serverKeyBytes, LABEL_SERVER_WRITE_KEY, seed, tmp = doTLS10PRF(serverKeyBytes, LABEL_SERVER_WRITE_KEY, seed,
expandedKeyLength, md5, sha); expandedKeyLength, md5, sha);
serverCipherKey = new SecretKeySpec(tmp, alg); serverCipherKey = new SecretKeySpec(tmp, alg);
if (ivLength != 0) { if (ivLength != 0) {
tmp = new byte[ivLength]; tmp = new byte[ivLength];
byte[] block = doPRF(null, LABEL_IV_BLOCK, seed, byte[] block = doTLS10PRF(null, LABEL_IV_BLOCK, seed,
ivLength << 1, md5, sha); ivLength << 1, md5, sha);
System.arraycopy(block, 0, tmp, 0, ivLength); System.arraycopy(block, 0, tmp, 0, ivLength);
clientIv = new IvParameterSpec(tmp); clientIv = new IvParameterSpec(tmp);
...@@ -216,6 +239,7 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi { ...@@ -216,6 +239,7 @@ public final class TlsKeyMaterialGenerator extends KeyGeneratorSpi {
serverIv = new IvParameterSpec(tmp); serverIv = new IvParameterSpec(tmp);
} }
} else { } else {
// SSLv3
tmp = new byte[expandedKeyLength]; tmp = new byte[expandedKeyLength];
md5.update(clientKeyBytes); md5.update(clientKeyBytes);
......
/* /*
* Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 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
...@@ -64,12 +64,14 @@ public final class TlsMasterSecretGenerator extends KeyGeneratorSpi { ...@@ -64,12 +64,14 @@ public final class TlsMasterSecretGenerator extends KeyGeneratorSpi {
} }
this.spec = (TlsMasterSecretParameterSpec)params; this.spec = (TlsMasterSecretParameterSpec)params;
if ("RAW".equals(spec.getPremasterSecret().getFormat()) == false) { if ("RAW".equals(spec.getPremasterSecret().getFormat()) == false) {
throw new InvalidAlgorithmParameterException("Key format must be RAW"); throw new InvalidAlgorithmParameterException(
"Key format must be RAW");
} }
protocolVersion = (spec.getMajorVersion() << 8) | spec.getMinorVersion(); protocolVersion = (spec.getMajorVersion() << 8)
if ((protocolVersion < 0x0300) || (protocolVersion > 0x0302)) { | spec.getMinorVersion();
throw new InvalidAlgorithmParameterException if ((protocolVersion < 0x0300) || (protocolVersion > 0x0303)) {
("Only SSL 3.0, TLS 1.0, and TLS 1.1 supported"); throw new InvalidAlgorithmParameterException(
"Only SSL 3.0, TLS 1.0/1.1/1.2 supported");
} }
} }
...@@ -79,8 +81,8 @@ public final class TlsMasterSecretGenerator extends KeyGeneratorSpi { ...@@ -79,8 +81,8 @@ public final class TlsMasterSecretGenerator extends KeyGeneratorSpi {
protected SecretKey engineGenerateKey() { protected SecretKey engineGenerateKey() {
if (spec == null) { if (spec == null) {
throw new IllegalStateException throw new IllegalStateException(
("TlsMasterSecretGenerator must be initialized"); "TlsMasterSecretGenerator must be initialized");
} }
SecretKey premasterKey = spec.getPremasterSecret(); SecretKey premasterKey = spec.getPremasterSecret();
byte[] premaster = premasterKey.getEncoded(); byte[] premaster = premasterKey.getEncoded();
...@@ -103,7 +105,11 @@ public final class TlsMasterSecretGenerator extends KeyGeneratorSpi { ...@@ -103,7 +105,11 @@ public final class TlsMasterSecretGenerator extends KeyGeneratorSpi {
if (protocolVersion >= 0x0301) { if (protocolVersion >= 0x0301) {
byte[] seed = concat(clientRandom, serverRandom); byte[] seed = concat(clientRandom, serverRandom);
master = doPRF(premaster, LABEL_MASTER_SECRET, seed, 48); master = ((protocolVersion >= 0x0303) ?
doTLS12PRF(premaster, LABEL_MASTER_SECRET, seed, 48,
spec.getPRFHashAlg(), spec.getPRFHashLength(),
spec.getPRFBlockSize()) :
doTLS10PRF(premaster, LABEL_MASTER_SECRET, seed, 48));
} else { } else {
master = new byte[48]; master = new byte[48];
MessageDigest md5 = MessageDigest.getInstance("MD5"); MessageDigest md5 = MessageDigest.getInstance("MD5");
...@@ -124,7 +130,8 @@ public final class TlsMasterSecretGenerator extends KeyGeneratorSpi { ...@@ -124,7 +130,8 @@ public final class TlsMasterSecretGenerator extends KeyGeneratorSpi {
} }
return new TlsMasterSecretKey(master, premasterMajor, premasterMinor); return new TlsMasterSecretKey(master, premasterMajor,
premasterMinor);
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
throw new ProviderException(e); throw new ProviderException(e);
} catch (DigestException e) { } catch (DigestException e) {
......
/* /*
* Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 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
...@@ -37,11 +37,15 @@ import sun.security.internal.spec.TlsPrfParameterSpec; ...@@ -37,11 +37,15 @@ import sun.security.internal.spec.TlsPrfParameterSpec;
/** /**
* KeyGenerator implementation for the TLS PRF function. * KeyGenerator implementation for the TLS PRF function.
* <p>
* This class duplicates the HMAC functionality (RFC 2104) with
* performance optimizations (e.g. XOR'ing keys with padding doesn't
* need to be redone for each HMAC operation).
* *
* @author Andreas Sterbenz * @author Andreas Sterbenz
* @since 1.6 * @since 1.6
*/ */
public final class TlsPrfGenerator extends KeyGeneratorSpi { abstract class TlsPrfGenerator extends KeyGeneratorSpi {
// magic constants and utility functions, also used by other files // magic constants and utility functions, also used by other files
// in this package // in this package
...@@ -69,8 +73,10 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi { ...@@ -69,8 +73,10 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi {
* TLS HMAC "inner" and "outer" padding. This isn't a function * TLS HMAC "inner" and "outer" padding. This isn't a function
* of the digest algorithm. * of the digest algorithm.
*/ */
private static final byte[] HMAC_ipad = genPad((byte)0x36, 64); private static final byte[] HMAC_ipad64 = genPad((byte)0x36, 64);
private static final byte[] HMAC_opad = genPad((byte)0x5c, 64); private static final byte[] HMAC_ipad128 = genPad((byte)0x36, 128);
private static final byte[] HMAC_opad64 = genPad((byte)0x5c, 64);
private static final byte[] HMAC_opad128 = genPad((byte)0x5c, 128);
// SSL3 magic mix constants ("A", "BB", "CCC", ...) // SSL3 magic mix constants ("A", "BB", "CCC", ...)
final static byte[][] SSL3_CONST = genConst(); final static byte[][] SSL3_CONST = genConst();
...@@ -123,8 +129,8 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi { ...@@ -123,8 +129,8 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi {
this.spec = (TlsPrfParameterSpec)params; this.spec = (TlsPrfParameterSpec)params;
SecretKey key = spec.getSecret(); SecretKey key = spec.getSecret();
if ((key != null) && ("RAW".equals(key.getFormat()) == false)) { if ((key != null) && ("RAW".equals(key.getFormat()) == false)) {
throw new InvalidAlgorithmParameterException throw new InvalidAlgorithmParameterException(
("Key encoding format must be RAW"); "Key encoding format must be RAW");
} }
} }
...@@ -132,17 +138,21 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi { ...@@ -132,17 +138,21 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi {
throw new InvalidParameterException(MSG); throw new InvalidParameterException(MSG);
} }
protected SecretKey engineGenerateKey() { SecretKey engineGenerateKey0(boolean tls12) {
if (spec == null) { if (spec == null) {
throw new IllegalStateException throw new IllegalStateException(
("TlsPrfGenerator must be initialized"); "TlsPrfGenerator must be initialized");
} }
SecretKey key = spec.getSecret(); SecretKey key = spec.getSecret();
byte[] secret = (key == null) ? null : key.getEncoded(); byte[] secret = (key == null) ? null : key.getEncoded();
try { try {
byte[] labelBytes = spec.getLabel().getBytes("UTF8"); byte[] labelBytes = spec.getLabel().getBytes("UTF8");
int n = spec.getOutputLength(); int n = spec.getOutputLength();
byte[] prfBytes = doPRF(secret, labelBytes, spec.getSeed(), n); byte[] prfBytes = (tls12 ?
doTLS12PRF(secret, labelBytes, spec.getSeed(), n,
spec.getPRFHashAlg(), spec.getPRFHashLength(),
spec.getPRFBlockSize()) :
doTLS10PRF(secret, labelBytes, spec.getSeed(), n));
return new SecretKeySpec(prfBytes, "TlsPrf"); return new SecretKeySpec(prfBytes, "TlsPrf");
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
throw new ProviderException("Could not generate PRF", e); throw new ProviderException("Could not generate PRF", e);
...@@ -151,16 +161,67 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi { ...@@ -151,16 +161,67 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi {
} }
} }
static final byte[] doPRF(byte[] secret, byte[] labelBytes, byte[] seed, static byte[] doTLS12PRF(byte[] secret, byte[] labelBytes,
int outputLength) throws NoSuchAlgorithmException, DigestException { byte[] seed, int outputLength,
String prfHash, int prfHashLength, int prfBlockSize)
throws NoSuchAlgorithmException, DigestException {
if (prfHash == null) {
throw new NoSuchAlgorithmException("Unspecified PRF algorithm");
}
MessageDigest prfMD = MessageDigest.getInstance(prfHash);
return doTLS12PRF(secret, labelBytes, seed, outputLength,
prfMD, prfHashLength, prfBlockSize);
}
static byte[] doTLS12PRF(byte[] secret, byte[] labelBytes,
byte[] seed, int outputLength,
MessageDigest mdPRF, int mdPRFLen, int mdPRFBlockSize)
throws DigestException {
if (secret == null) {
secret = B0;
}
// If we have a long secret, digest it first.
if (secret.length > mdPRFBlockSize) {
secret = mdPRF.digest(secret);
}
byte[] output = new byte[outputLength];
byte [] ipad;
byte [] opad;
switch (mdPRFBlockSize) {
case 64:
ipad = HMAC_ipad64.clone();
opad = HMAC_opad64.clone();
break;
case 128:
ipad = HMAC_ipad128.clone();
opad = HMAC_opad128.clone();
break;
default:
throw new DigestException("Unexpected block size.");
}
// P_HASH(Secret, label + seed)
expand(mdPRF, mdPRFLen, secret, 0, secret.length, labelBytes,
seed, output, ipad, opad);
return output;
}
static byte[] doTLS10PRF(byte[] secret, byte[] labelBytes,
byte[] seed, int outputLength) throws NoSuchAlgorithmException,
DigestException {
MessageDigest md5 = MessageDigest.getInstance("MD5"); MessageDigest md5 = MessageDigest.getInstance("MD5");
MessageDigest sha = MessageDigest.getInstance("SHA1"); MessageDigest sha = MessageDigest.getInstance("SHA1");
return doPRF(secret, labelBytes, seed, outputLength, md5, sha); return doTLS10PRF(secret, labelBytes, seed, outputLength, md5, sha);
} }
static final byte[] doPRF(byte[] secret, byte[] labelBytes, byte[] seed, static byte[] doTLS10PRF(byte[] secret, byte[] labelBytes,
int outputLength, MessageDigest md5, MessageDigest sha) byte[] seed, int outputLength, MessageDigest md5,
throws DigestException { MessageDigest sha) throws DigestException {
/* /*
* Split the secret into two halves S1 and S2 of same length. * Split the secret into two halves S1 and S2 of same length.
* S1 is taken from the first half of the secret, S2 from the * S1 is taken from the first half of the secret, S2 from the
...@@ -183,10 +244,12 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi { ...@@ -183,10 +244,12 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi {
byte[] output = new byte[outputLength]; byte[] output = new byte[outputLength];
// P_MD5(S1, label + seed) // P_MD5(S1, label + seed)
expand(md5, 16, secret, 0, seclen, labelBytes, seed, output); expand(md5, 16, secret, 0, seclen, labelBytes, seed, output,
HMAC_ipad64.clone(), HMAC_opad64.clone());
// P_SHA-1(S2, label + seed) // P_SHA-1(S2, label + seed)
expand(sha, 20, secret, off, seclen, labelBytes, seed, output); expand(sha, 20, secret, off, seclen, labelBytes, seed, output,
HMAC_ipad64.clone(), HMAC_opad64.clone());
return output; return output;
} }
...@@ -201,16 +264,13 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi { ...@@ -201,16 +264,13 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi {
* @param seed the seed * @param seed the seed
* @param output the output array * @param output the output array
*/ */
private static final void expand(MessageDigest digest, int hmacSize, private static void expand(MessageDigest digest, int hmacSize,
byte[] secret, int secOff, int secLen, byte[] label, byte[] seed, byte[] secret, int secOff, int secLen, byte[] label, byte[] seed,
byte[] output) throws DigestException { byte[] output, byte[] pad1, byte[] pad2) throws DigestException {
/* /*
* modify the padding used, by XORing the key into our copy of that * modify the padding used, by XORing the key into our copy of that
* padding. That's to avoid doing that for each HMAC computation. * padding. That's to avoid doing that for each HMAC computation.
*/ */
byte[] pad1 = HMAC_ipad.clone();
byte[] pad2 = HMAC_opad.clone();
for (int i = 0; i < secLen; i++) { for (int i = 0; i < secLen; i++) {
pad1[i] ^= secret[i + secOff]; pad1[i] ^= secret[i + secOff];
pad2[i] ^= secret[i + secOff]; pad2[i] ^= secret[i + secOff];
...@@ -275,7 +335,34 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi { ...@@ -275,7 +335,34 @@ public final class TlsPrfGenerator extends KeyGeneratorSpi {
} }
remaining -= k; remaining -= k;
} }
}
/**
* A KeyGenerator implementation that supports TLS 1.2.
* <p>
* TLS 1.2 uses a different hash algorithm than 1.0/1.1 for the PRF
* calculations. As of 2010, there is no PKCS11-level support for TLS
* 1.2 PRF calculations, and no known OS's have an internal variant
* we could use. Therefore for TLS 1.2, we are updating JSSE to request
* a different provider algorithm: "SunTls12Prf". If we reused the
* name "SunTlsPrf", the PKCS11 provider would need be updated to
* fail correctly when presented with the wrong version number
* (via Provider.Service.supportsParameters()), and add the
* appropriate supportsParamters() checks into KeyGenerators (not
* currently there).
*/
static public class V12 extends TlsPrfGenerator {
protected SecretKey engineGenerateKey() {
return engineGenerateKey0(true);
}
} }
/**
* A KeyGenerator implementation that supports TLS 1.0/1.1.
*/
static public class V10 extends TlsPrfGenerator {
protected SecretKey engineGenerateKey() {
return engineGenerateKey0(false);
}
}
} }
/* /*
* Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 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
...@@ -69,8 +69,8 @@ public final class TlsRsaPremasterSecretGenerator extends KeyGeneratorSpi { ...@@ -69,8 +69,8 @@ public final class TlsRsaPremasterSecretGenerator extends KeyGeneratorSpi {
protected SecretKey engineGenerateKey() { protected SecretKey engineGenerateKey() {
if (spec == null) { if (spec == null) {
throw new IllegalStateException throw new IllegalStateException(
("TlsRsaPremasterSecretGenerator must be initialized"); "TlsRsaPremasterSecretGenerator must be initialized");
} }
if (random == null) { if (random == null) {
random = new SecureRandom(); random = new SecureRandom();
......
...@@ -76,9 +76,9 @@ public class ServiceName { ...@@ -76,9 +76,9 @@ public class ServiceName {
/** /**
* The vendor of the JMX specification implemented by this product. * The vendor of the JMX specification implemented by this product.
* <BR> * <BR>
* The value is <CODE>Sun Microsystems</CODE>. * The value is <CODE>Oracle Corporation</CODE>.
*/ */
public static final String JMX_SPEC_VENDOR = "Sun Microsystems"; public static final String JMX_SPEC_VENDOR = "Oracle Corporation";
/** /**
* The name of this product implementing the JMX specification. * The name of this product implementing the JMX specification.
...@@ -91,7 +91,7 @@ public class ServiceName { ...@@ -91,7 +91,7 @@ public class ServiceName {
* The name of the vendor of this product implementing the * The name of the vendor of this product implementing the
* JMX specification. * JMX specification.
* <BR> * <BR>
* The value is <CODE>Sun Microsystems</CODE>. * The value is <CODE>Oracle Corporation</CODE>.
*/ */
public static final String JMX_IMPL_VENDOR = "Sun Microsystems"; public static final String JMX_IMPL_VENDOR = "Oracle Corporation";
} }
...@@ -27,7 +27,7 @@ package com.sun.jmx.snmp; ...@@ -27,7 +27,7 @@ package com.sun.jmx.snmp;
/** /**
* Used for storing default values used by SNMP Runtime services. * Used for storing default values used by SNMP Runtime services.
* <p><b>This API is a Sun Microsystems internal API and is subject * <p><b>This API is an Oracle Corporation internal API and is subject
* to change without notice.</b></p> * to change without notice.</b></p>
*/ */
public class ServiceName { public class ServiceName {
...@@ -144,16 +144,16 @@ public class ServiceName { ...@@ -144,16 +144,16 @@ public class ServiceName {
/** /**
* The vendor of the JMX specification implemented by this product. * The vendor of the JMX specification implemented by this product.
* <BR> * <BR>
* The value is <CODE>Sun Microsystems</CODE>. * The value is <CODE>Oracle Corporation</CODE>.
*/ */
public static final String JMX_SPEC_VENDOR = "Sun Microsystems"; public static final String JMX_SPEC_VENDOR = "Oracle Corporation";
/** /**
* The name of the vendor of this product implementing the JMX specification. * The name of the vendor of this product implementing the JMX specification.
* <BR> * <BR>
* The value is <CODE>Sun Microsystems</CODE>. * The value is <CODE>Oracle Corporation</CODE>.
*/ */
public static final String JMX_IMPL_VENDOR = "Sun Microsystems"; public static final String JMX_IMPL_VENDOR = "Oracle Corporation";
/** /**
* The build number of the current product version, of the form <CODE>rXX</CODE>. * The build number of the current product version, of the form <CODE>rXX</CODE>.
......
...@@ -30,7 +30,7 @@ questions. ...@@ -30,7 +30,7 @@ questions.
</head> </head>
<body bgcolor="white"> <body bgcolor="white">
This package contains Sun Microsystem's platform extension to This package contains Oracle Corporation's platform extension to
the implementation of the the implementation of the
<a href="{@docRoot}/../../../../api/java/lang/management/package-summary.html"> <a href="{@docRoot}/../../../../api/java/lang/management/package-summary.html">
java.lang.management</a> API and also defines the management java.lang.management</a> API and also defines the management
......
/* /*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 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
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
package java.awt; package java.awt;
import java.beans.ConstructorProperties;
/** /**
* The <code>BasicStroke</code> class defines a basic set of rendering * The <code>BasicStroke</code> class defines a basic set of rendering
* attributes for the outlines of graphics primitives, which are rendered * attributes for the outlines of graphics primitives, which are rendered
...@@ -183,6 +185,7 @@ public class BasicStroke implements Stroke { ...@@ -183,6 +185,7 @@ public class BasicStroke implements Stroke {
* <code>dash</code> is zero * <code>dash</code> is zero
* @throws IllegalArgumentException if dash lengths are all zero. * @throws IllegalArgumentException if dash lengths are all zero.
*/ */
@ConstructorProperties({ "lineWidth", "endCap", "lineJoin", "miterLimit", "dashArray", "dashPhase" })
public BasicStroke(float width, int cap, int join, float miterlimit, public BasicStroke(float width, int cap, int join, float miterlimit,
float dash[], float dash_phase) { float dash[], float dash_phase) {
if (width < 0.0f) { if (width < 0.0f) {
......
/* /*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 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
...@@ -29,6 +29,7 @@ import java.awt.geom.Point2D; ...@@ -29,6 +29,7 @@ import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.awt.geom.AffineTransform; import java.awt.geom.AffineTransform;
import java.awt.image.ColorModel; import java.awt.image.ColorModel;
import java.beans.ConstructorProperties;
/** /**
* The <code>GradientPaint</code> class provides a way to fill * The <code>GradientPaint</code> class provides a way to fill
...@@ -166,6 +167,7 @@ public class GradientPaint implements Paint { ...@@ -166,6 +167,7 @@ public class GradientPaint implements Paint {
* @throws NullPointerException if either one of colors or points * @throws NullPointerException if either one of colors or points
* is null * is null
*/ */
@ConstructorProperties({ "point1", "color1", "point2", "color2", "cyclic" })
public GradientPaint(Point2D pt1, public GradientPaint(Point2D pt1,
Color color1, Color color1,
Point2D pt2, Point2D pt2,
......
...@@ -126,7 +126,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { ...@@ -126,7 +126,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable {
/** /**
* Place the component centered along the edge of its display area * Place the component centered along the edge of its display area
* associated with the start of a page for the current * associated with the start of a page for the current
* <code>ComponentOrienation</code>. Equal to NORTH for horizontal * {@code ComponentOrientation}. Equal to NORTH for horizontal
* orientations. * orientations.
*/ */
public static final int PAGE_START = 19; public static final int PAGE_START = 19;
...@@ -134,7 +134,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { ...@@ -134,7 +134,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable {
/** /**
* Place the component centered along the edge of its display area * Place the component centered along the edge of its display area
* associated with the end of a page for the current * associated with the end of a page for the current
* <code>ComponentOrienation</code>. Equal to SOUTH for horizontal * {@code ComponentOrientation}. Equal to SOUTH for horizontal
* orientations. * orientations.
*/ */
public static final int PAGE_END = 20; public static final int PAGE_END = 20;
...@@ -142,7 +142,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { ...@@ -142,7 +142,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable {
/** /**
* Place the component centered along the edge of its display area where * Place the component centered along the edge of its display area where
* lines of text would normally begin for the current * lines of text would normally begin for the current
* <code>ComponentOrienation</code>. Equal to WEST for horizontal, * {@code ComponentOrientation}. Equal to WEST for horizontal,
* left-to-right orientations and EAST for horizontal, right-to-left * left-to-right orientations and EAST for horizontal, right-to-left
* orientations. * orientations.
*/ */
...@@ -151,7 +151,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { ...@@ -151,7 +151,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable {
/** /**
* Place the component centered along the edge of its display area where * Place the component centered along the edge of its display area where
* lines of text would normally end for the current * lines of text would normally end for the current
* <code>ComponentOrienation</code>. Equal to EAST for horizontal, * {@code ComponentOrientation}. Equal to EAST for horizontal,
* left-to-right orientations and WEST for horizontal, right-to-left * left-to-right orientations and WEST for horizontal, right-to-left
* orientations. * orientations.
*/ */
...@@ -160,7 +160,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { ...@@ -160,7 +160,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable {
/** /**
* Place the component in the corner of its display area where * Place the component in the corner of its display area where
* the first line of text on a page would normally begin for the current * the first line of text on a page would normally begin for the current
* <code>ComponentOrienation</code>. Equal to NORTHWEST for horizontal, * {@code ComponentOrientation}. Equal to NORTHWEST for horizontal,
* left-to-right orientations and NORTHEAST for horizontal, right-to-left * left-to-right orientations and NORTHEAST for horizontal, right-to-left
* orientations. * orientations.
*/ */
...@@ -169,7 +169,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { ...@@ -169,7 +169,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable {
/** /**
* Place the component in the corner of its display area where * Place the component in the corner of its display area where
* the first line of text on a page would normally end for the current * the first line of text on a page would normally end for the current
* <code>ComponentOrienation</code>. Equal to NORTHEAST for horizontal, * {@code ComponentOrientation}. Equal to NORTHEAST for horizontal,
* left-to-right orientations and NORTHWEST for horizontal, right-to-left * left-to-right orientations and NORTHWEST for horizontal, right-to-left
* orientations. * orientations.
*/ */
...@@ -178,7 +178,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { ...@@ -178,7 +178,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable {
/** /**
* Place the component in the corner of its display area where * Place the component in the corner of its display area where
* the last line of text on a page would normally start for the current * the last line of text on a page would normally start for the current
* <code>ComponentOrienation</code>. Equal to SOUTHWEST for horizontal, * {@code ComponentOrientation}. Equal to SOUTHWEST for horizontal,
* left-to-right orientations and SOUTHEAST for horizontal, right-to-left * left-to-right orientations and SOUTHEAST for horizontal, right-to-left
* orientations. * orientations.
*/ */
...@@ -187,7 +187,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { ...@@ -187,7 +187,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable {
/** /**
* Place the component in the corner of its display area where * Place the component in the corner of its display area where
* the last line of text on a page would normally end for the current * the last line of text on a page would normally end for the current
* <code>ComponentOrienation</code>. Equal to SOUTHEAST for horizontal, * {@code ComponentOrientation}. Equal to SOUTHEAST for horizontal,
* left-to-right orientations and SOUTHWEST for horizontal, right-to-left * left-to-right orientations and SOUTHWEST for horizontal, right-to-left
* orientations. * orientations.
*/ */
...@@ -437,7 +437,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { ...@@ -437,7 +437,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable {
* <code>LINE_START</code>, <code>LINE_END</code>, * <code>LINE_START</code>, <code>LINE_END</code>,
* <code>FIRST_LINE_START</code>, <code>FIRST_LINE_END</code>, * <code>FIRST_LINE_START</code>, <code>FIRST_LINE_END</code>,
* <code>LAST_LINE_START</code> and <code>LAST_LINE_END</code>. The * <code>LAST_LINE_START</code> and <code>LAST_LINE_END</code>. The
* baseline relvative values are: * baseline relative values are:
* <code>BASELINE</code>, <code>BASELINE_LEADING</code>, * <code>BASELINE</code>, <code>BASELINE_LEADING</code>,
* <code>BASELINE_TRAILING</code>, * <code>BASELINE_TRAILING</code>,
* <code>ABOVE_BASELINE</code>, <code>ABOVE_BASELINE_LEADING</code>, * <code>ABOVE_BASELINE</code>, <code>ABOVE_BASELINE_LEADING</code>,
......
/* /*
* Copyright (c) 2006, 2008, 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
...@@ -26,10 +26,10 @@ ...@@ -26,10 +26,10 @@
package java.awt; package java.awt;
import java.awt.geom.AffineTransform; import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.awt.image.ColorModel; import java.awt.image.ColorModel;
import java.beans.ConstructorProperties;
/** /**
* The {@code LinearGradientPaint} class provides a way to fill * The {@code LinearGradientPaint} class provides a way to fill
...@@ -271,6 +271,7 @@ public final class LinearGradientPaint extends MultipleGradientPaint { ...@@ -271,6 +271,7 @@ public final class LinearGradientPaint extends MultipleGradientPaint {
* or a {@code fractions} value is less than 0.0 or greater than 1.0, * or a {@code fractions} value is less than 0.0 or greater than 1.0,
* or the {@code fractions} are not provided in strictly increasing order * or the {@code fractions} are not provided in strictly increasing order
*/ */
@ConstructorProperties({ "startPoint", "endPoint", "fractions", "colors", "cycleMethod", "colorSpace", "transform" })
public LinearGradientPaint(Point2D start, Point2D end, public LinearGradientPaint(Point2D start, Point2D end,
float[] fractions, Color[] colors, float[] fractions, Color[] colors,
CycleMethod cycleMethod, CycleMethod cycleMethod,
......
/* /*
* Copyright (c) 2006, 2008, 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
...@@ -29,6 +29,7 @@ import java.awt.geom.AffineTransform; ...@@ -29,6 +29,7 @@ import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.awt.image.ColorModel; import java.awt.image.ColorModel;
import java.beans.ConstructorProperties;
/** /**
* The {@code RadialGradientPaint} class provides a way to fill a shape with * The {@code RadialGradientPaint} class provides a way to fill a shape with
...@@ -428,6 +429,7 @@ public final class RadialGradientPaint extends MultipleGradientPaint { ...@@ -428,6 +429,7 @@ public final class RadialGradientPaint extends MultipleGradientPaint {
* or a {@code fractions} value is less than 0.0 or greater than 1.0, * or a {@code fractions} value is less than 0.0 or greater than 1.0,
* or the {@code fractions} are not provided in strictly increasing order * or the {@code fractions} are not provided in strictly increasing order
*/ */
@ConstructorProperties({ "centerPoint", "radius", "focusPoint", "fractions", "colors", "cycleMethod", "colorSpace", "transform" })
public RadialGradientPaint(Point2D center, public RadialGradientPaint(Point2D center,
float radius, float radius,
Point2D focus, Point2D focus,
......
...@@ -213,7 +213,8 @@ public class Scrollbar extends Component implements Adjustable, Accessible { ...@@ -213,7 +213,8 @@ public class Scrollbar extends Component implements Adjustable, Accessible {
* The size of the <code>Scrollbar</code>'s bubble. * The size of the <code>Scrollbar</code>'s bubble.
* When a scroll bar is used to select a range of values, * When a scroll bar is used to select a range of values,
* the visibleAmount represents the size of this range. * the visibleAmount represents the size of this range.
* This is visually indicated by the size of the bubble. * Depending on platform, this may be visually indicated
* by the size of the bubble.
* *
* @serial * @serial
* @see #getVisibleAmount * @see #getVisibleAmount
...@@ -637,6 +638,8 @@ public class Scrollbar extends Component implements Adjustable, Accessible { ...@@ -637,6 +638,8 @@ public class Scrollbar extends Component implements Adjustable, Accessible {
* bubble (also called a thumb or scroll box), usually gives a * bubble (also called a thumb or scroll box), usually gives a
* visual representation of the relationship of the visible * visual representation of the relationship of the visible
* amount to the range of the scroll bar. * amount to the range of the scroll bar.
* Note that depending on platform, the value of the visible amount property
* may not be visually indicated by the size of the bubble.
* <p> * <p>
* The scroll bar's bubble may not be displayed when it is not * The scroll bar's bubble may not be displayed when it is not
* moveable (e.g. when it takes up the entire length of the * moveable (e.g. when it takes up the entire length of the
...@@ -670,6 +673,8 @@ public class Scrollbar extends Component implements Adjustable, Accessible { ...@@ -670,6 +673,8 @@ public class Scrollbar extends Component implements Adjustable, Accessible {
* bubble (also called a thumb or scroll box), usually gives a * bubble (also called a thumb or scroll box), usually gives a
* visual representation of the relationship of the visible * visual representation of the relationship of the visible
* amount to the range of the scroll bar. * amount to the range of the scroll bar.
* Note that depending on platform, the value of the visible amount property
* may not be visually indicated by the size of the bubble.
* <p> * <p>
* The scroll bar's bubble may not be displayed when it is not * The scroll bar's bubble may not be displayed when it is not
* moveable (e.g. when it takes up the entire length of the * moveable (e.g. when it takes up the entire length of the
......
...@@ -1831,7 +1831,11 @@ public abstract class Toolkit { ...@@ -1831,7 +1831,11 @@ public abstract class Toolkit {
desktopProperties.put(name, newValue); desktopProperties.put(name, newValue);
} }
desktopPropsSupport.firePropertyChange(name, oldValue, newValue); // Don't fire change event if old and new values are null.
// It helps to avoid recursive resending of WM_THEMECHANGED
if (oldValue != null || newValue != null) {
desktopPropsSupport.firePropertyChange(name, oldValue, newValue);
}
} }
/** /**
......
/* /*
* Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 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
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
package java.awt.geom; package java.awt.geom;
import java.awt.Shape; import java.awt.Shape;
import java.beans.ConstructorProperties;
/** /**
* The <code>AffineTransform</code> class represents a 2D affine transform * The <code>AffineTransform</code> class represents a 2D affine transform
...@@ -508,6 +509,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { ...@@ -508,6 +509,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable {
* @param m12 the Y coordinate translation element of the 3x3 matrix * @param m12 the Y coordinate translation element of the 3x3 matrix
* @since 1.2 * @since 1.2
*/ */
@ConstructorProperties({ "scaleX", "shearY", "shearX", "scaleY", "translateX", "translateY" })
public AffineTransform(float m00, float m10, public AffineTransform(float m00, float m10,
float m01, float m11, float m01, float m11,
float m02, float m12) { float m02, float m12) {
......
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. 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.dyn;
import java.lang.annotation.*;
/**
* Annotation on InvokeDynamic method calls which requests the JVM to use a specific
* <a href="package-summary.html#bsm">bootstrap method</a>
* to link the call. This annotation is not retained as such in the class file,
* but is transformed into a constant-pool entry for the invokedynamic instruction which
* specifies the desired bootstrap method.
* <p>
* If only the <code>value</code> is given, it must name a subclass of {@link CallSite}
* with a constructor which accepts a class, string, and method type.
* If the <code>value</code> and <code>name</code> are both given, there must be
* a static method in the given class of the given name which accepts a class, string,
* and method type, and returns a reference coercible to {@link CallSite}.
* <p>
* This annotation can be placed either on the return type of a single {@link InvokeDynamic}
* call (see examples) or else it can be placed on an enclosing class or method, where it
* determines a default bootstrap method for any {@link InvokeDynamic} calls which are not
* specifically annotated with a bootstrap method.
* Every {@link InvokeDynamic} call must be given a bootstrap method.
* <p>
* Examples:
<blockquote><pre>
&#064;BootstrapMethod(value=MyLanguageRuntime.class, name="bootstrapDynamic")
String x = (String) InvokeDynamic.greet();
//BSM => MyLanguageRuntime.bootstrapDynamic(Here.class, "greet", methodType(String.class))
&#064;BootstrapMethod(MyCallSite.class)
void example() throws Throwable {
InvokeDynamic.greet();
//BSM => new MyCallSite(Here.class, "greet", methodType(void.class))
}
</pre></blockquote>
* <p>
*/
@Target({ElementType.TYPE_USE,
// For defaulting every indy site within a class or method; cf. @SuppressWarnings:
ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR
})
@Retention(RetentionPolicy.SOURCE)
public @interface BootstrapMethod {
/** The class containing the bootstrap method. */
Class<?> value();
/** The name of the bootstrap method.
* If this is the empty string, an instance of the bootstrap class is created,
* and a constructor is invoked.
* Otherwise, there must be a static method of the required name.
*/
String name() default ""; // empty string denotes a constructor with 'new'
/** The argument types of the bootstrap method, as passed out by the JVM.
* There is usually no reason to override the default.
*/
Class<?>[] arguments() default {Class.class, String.class, MethodType.class};
}
...@@ -25,56 +25,26 @@ ...@@ -25,56 +25,26 @@
package java.dyn; package java.dyn;
import sun.dyn.Access; import sun.dyn.*;
import sun.dyn.MemberName; import java.util.Collection;
import sun.dyn.CallSiteImpl;
/** /**
* A {@code CallSite} reifies an {@code invokedynamic} instruction from bytecode, * A {@code CallSite} is a holder for a variable {@link MethodHandle},
* and controls its linkage. * which is called its {@code target}.
* Every linked {@code CallSite} object corresponds to a distinct instance * Every call to a {@code CallSite} is delegated to the site's current target.
* of the {@code invokedynamic} instruction, and vice versa.
* <p> * <p>
* Every linked {@code CallSite} object has one state variable, * A call site is initially created in an <em>unlinked</em> state,
* a {@link MethodHandle} reference called the {@code target}. * which is distinguished by a null target variable.
* This reference is never null. Though it can change its value * Before the call site may be invoked (and before certain other
* successive values must always have exactly the {@link MethodType method type} * operations are attempted), the call site must be linked to
* called for by the bytecodes of the associated {@code invokedynamic} instruction * a non-null target.
* <p> * <p>
* It is the responsibility of each class's * A call site may be <em>relinked</em> by changing its target.
* {@link Linkage#registerBootstrapMethod(Class, MethodHandle) bootstrap method} * The new target must be non-null and must have the same
* to produce call sites which have been pre-linked to an initial target method. * {@linkplain MethodHandle#type() type}
* The required {@link MethodType type} for the target method is a parameter * as the previous target.
* to each bootstrap method call. * Thus, though a call site can be relinked to a series of
* <p> * successive targets, it cannot change its type.
* The bootstrap method may elect to produce call sites of a
* language-specific subclass of {@code CallSite}. In such a case,
* the subclass may claim responsibility for initializing its target to
* a non-null value, by overriding {@link #initialTarget}.
* <p>
* An {@code invokedynamic} instruction which has not yet been executed
* is said to be <em>unlinked</em>. When an unlinked call site is executed,
* the containing class's bootstrap method is called to manufacture a call site,
* for the instruction. If the bootstrap method does not assign a non-null
* value to the new call site's target variable, the method {@link #initialTarget}
* is called to produce the new call site's first target method.
* <p>
* A freshly-created {@code CallSite} object is not yet in a linked state.
* An unlinked {@code CallSite} object reports null for its {@code callerClass}.
* When the JVM receives a {@code CallSite} object from a bootstrap method,
* it first ensures that its target is non-null and of the correct type.
* The JVM then links the {@code CallSite} object to the call site instruction,
* enabling the {@code callerClass} to return the class in which the instruction occurs.
* <p>
* Next, the JVM links the instruction to the {@code CallSite}, at which point
* any further execution of the {@code invokedynamic} instruction implicitly
* invokes the current target of the {@code CallSite} object.
* After this two-way linkage, both the instruction and the {@code CallSite}
* object are said to be linked.
* <p>
* This state of linkage continues until the method containing the
* dynamic call site is garbage collected, or the dynamic call site
* is invalidated by an explicit request.
* <p> * <p>
* Linkage happens once in the lifetime of any given {@code CallSite} object. * Linkage happens once in the lifetime of any given {@code CallSite} object.
* Because of call site invalidation, this linkage can be repeated for * Because of call site invalidation, this linkage can be repeated for
...@@ -87,6 +57,10 @@ import sun.dyn.CallSiteImpl; ...@@ -87,6 +57,10 @@ import sun.dyn.CallSiteImpl;
* Here is a sample use of call sites and bootstrap methods which links every * Here is a sample use of call sites and bootstrap methods which links every
* dynamic call site to print its arguments: * dynamic call site to print its arguments:
<blockquote><pre><!-- see indy-demo/src/PrintArgsDemo.java --> <blockquote><pre><!-- see indy-demo/src/PrintArgsDemo.java -->
&#064;BootstrapMethod(value=PrintArgsDemo.class, name="bootstrapDynamic")
static void test() throws Throwable {
InvokeDynamic.baz("baz arg", 2, 3.14);
}
private static void printArgs(Object... args) { private static void printArgs(Object... args) {
System.out.println(java.util.Arrays.deepToString(args)); System.out.println(java.util.Arrays.deepToString(args));
} }
...@@ -96,17 +70,16 @@ static { ...@@ -96,17 +70,16 @@ static {
Class thisClass = lookup.lookupClass(); // (who am I?) Class thisClass = lookup.lookupClass(); // (who am I?)
printArgs = lookup.findStatic(thisClass, printArgs = lookup.findStatic(thisClass,
"printArgs", MethodType.methodType(void.class, Object[].class)); "printArgs", MethodType.methodType(void.class, Object[].class));
Linkage.registerBootstrapMethod("bootstrapDynamic");
} }
private static CallSite bootstrapDynamic(Class caller, String name, MethodType type) { private static CallSite bootstrapDynamic(Class caller, String name, MethodType type) {
// ignore caller and name, but match the type: // ignore caller and name, but match the type:
return new CallSite(MethodHandles.collectArguments(printArgs, type)); return new CallSite(MethodHandles.collectArguments(printArgs, type));
} }
</pre></blockquote> </pre></blockquote>
* @see Linkage#registerBootstrapMethod(java.lang.Class, java.dyn.MethodHandle)
* @author John Rose, JSR 292 EG * @author John Rose, JSR 292 EG
*/ */
public class CallSite public class CallSite
implements MethodHandleProvider
{ {
private static final Access IMPL_TOKEN = Access.getToken(); private static final Access IMPL_TOKEN = Access.getToken();
...@@ -209,6 +182,7 @@ public class CallSite ...@@ -209,6 +182,7 @@ public class CallSite
* {@code InvokeDynamicBootstrapError}, which in turn causes the * {@code InvokeDynamicBootstrapError}, which in turn causes the
* linkage of the {@code invokedynamic} instruction to terminate * linkage of the {@code invokedynamic} instruction to terminate
* abnormally. * abnormally.
* @deprecated transitional form defined in EDR but removed in PFD
*/ */
protected MethodHandle initialTarget(Class<?> callerClass, String name, MethodType type) { protected MethodHandle initialTarget(Class<?> callerClass, String name, MethodType type) {
throw new InvokeDynamicBootstrapError("target must be initialized before call site is linked: "+name+type); throw new InvokeDynamicBootstrapError("target must be initialized before call site is linked: "+name+type);
...@@ -278,16 +252,44 @@ public class CallSite ...@@ -278,16 +252,44 @@ public class CallSite
*/ */
@Override @Override
public String toString() { public String toString() {
StringBuilder buf = new StringBuilder("CallSite#"); return "CallSite"+(target == null ? "" : target.type());
buf.append(hashCode()); }
if (!isLinked())
buf.append("[unlinked]"); /**
else * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
buf.append("[") * Produce a method handle equivalent to an invokedynamic instruction
.append("from ").append(vmmethod.getDeclaringClass().getName()) * which has been linked to this call site.
.append(" : ").append(getTarget().type()) * <p>If this call site is a {@link ConstantCallSite}, this method
.append(" => ").append(getTarget()) * simply returns the call site's target, since that will not change.
.append("]"); * <p>Otherwise, this method is equivalent to the following code:
return buf.toString(); * <p><blockquote><pre>
* MethodHandle getTarget, invoker, result;
* getTarget = MethodHandles.lookup().bind(this, "getTarget", MethodType.methodType(MethodHandle.class));
* invoker = MethodHandles.exactInvoker(this.type());
* result = MethodHandles.foldArguments(invoker, getTarget)
* </pre></blockquote>
* @return a method handle which always invokes this call site's current target
*/
public final MethodHandle dynamicInvoker() {
if (this instanceof ConstantCallSite)
return getTarget(); // will not change dynamically
MethodHandle getTarget = MethodHandleImpl.bindReceiver(IMPL_TOKEN, GET_TARGET, this);
MethodHandle invoker = MethodHandles.exactInvoker(this.type());
return MethodHandles.foldArguments(invoker, getTarget);
} }
private static final MethodHandle GET_TARGET;
static {
try {
GET_TARGET = MethodHandles.Lookup.IMPL_LOOKUP.
findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
} catch (NoAccessException ignore) {
throw new InternalError();
}
}
/** Implementation of {@link MethodHandleProvider} which returns {@code this.dynamicInvoker()}. */
public final MethodHandle asMethodHandle() { return dynamicInvoker(); }
/** Implementation of {@link MethodHandleProvider}, which returns {@code this.dynamicInvoker().asType(type)}. */
public final MethodHandle asMethodHandle(MethodType type) { return dynamicInvoker().asType(type); }
} }
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. 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.dyn;
import java.util.WeakHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
/**
* Lazily associate a computed value with (potentially) every class.
* @author John Rose, JSR 292 EG
*/
public abstract class ClassValue<T> {
/**
* Compute the given class's derived value for this {@code ClassValue}.
* <p>
* This method will be invoked within the first thread that accesses
* the value with the {@link #get}.
* <p>
* Normally, this method is invoked at most once per class,
* but it may be invoked again in case of subsequent invocations
* of {@link #remove} followed by {@link #get}.
*
* @return the computed value for this thread-local
*/
protected abstract T computeValue(Class<?> type);
/**
* Creates a new class value.
*/
protected ClassValue() {
}
/**
* Returns the value for the given class.
* If no value has yet been computed, it is obtained by
* by an invocation of the {@link #computeValue} method.
* <p>
* The actual installation of the value on the class
* is performed while the class's synchronization lock
* is held. At that point, if racing threads have
* computed values, one is chosen, and returned to
* all the racing threads.
*
* @return the current thread's value of this thread-local
*/
public T get(Class<?> type) {
ClassValueMap map = getMap(type);
if (map != null) {
Object x = map.get(this);
if (x != null) {
return (T) map.unmaskNull(x);
}
}
return setComputedValue(type);
}
/**
* Removes the associated value for the given class.
* If this value is subsequently {@linkplain #get read} for the same class,
* its value will be reinitialized by invoking its {@link #computeValue} method.
* This may result in an additional invocation of the
* {@code computeValue} method for the given class.
*/
public void remove(Class<?> type) {
ClassValueMap map = getMap(type);
if (map != null) {
synchronized (map) {
map.remove(this);
}
}
}
/// Implementation...
/** The hash code for this type is based on the identity of the object,
* and is well-dispersed for power-of-two tables.
*/
public final int hashCode() { return hashCode; }
private final int hashCode = HASH_CODES.getAndAdd(0x61c88647);
private static final AtomicInteger HASH_CODES = new AtomicInteger();
private static final AtomicInteger STORE_BARRIER = new AtomicInteger();
/** Slow path for {@link #get}. */
private T setComputedValue(Class<?> type) {
ClassValueMap map = getMap(type);
if (map == null) {
map = initializeMap(type);
}
T value = computeValue(type);
STORE_BARRIER.lazySet(0);
// All stores pending from computeValue are completed.
synchronized (map) {
// Warm up the table with a null entry.
map.preInitializeEntry(this);
}
// All stores pending from table expansion are completed.
synchronized (map) {
value = (T) map.initializeEntry(this, value);
// One might fear a possible race condition here
// if the code for map.put has flushed the write
// to map.table[*] before the writes to the Map.Entry
// are done. This is not possible, since we have
// warmed up the table with an empty entry.
}
return value;
}
// Replace this map by a per-class slot.
private static final WeakHashMap<Class<?>, ClassValueMap> ROOT
= new WeakHashMap<Class<?>, ClassValueMap>();
private static ClassValueMap getMap(Class<?> type) {
return ROOT.get(type);
}
private static ClassValueMap initializeMap(Class<?> type) {
synchronized (ClassValue.class) {
ClassValueMap map = ROOT.get(type);
if (map == null)
ROOT.put(type, map = new ClassValueMap());
return map;
}
}
static class ClassValueMap extends WeakHashMap<ClassValue, Object> {
/** Make sure this table contains an Entry for the given key, even if it is empty. */
void preInitializeEntry(ClassValue key) {
if (!this.containsKey(key))
this.put(key, null);
}
/** Make sure this table contains a non-empty Entry for the given key. */
Object initializeEntry(ClassValue key, Object value) {
Object prior = this.get(key);
if (prior != null) {
return unmaskNull(prior);
}
this.put(key, maskNull(value));
return value;
}
Object maskNull(Object x) {
return x == null ? this : x;
}
Object unmaskNull(Object x) {
return x == this ? null : x;
}
}
}
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. 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.dyn;
/**
* A {@code ConstantCallSite} is a {@link CallSite} whose target is permanent, and can never be changed.
* The only way to relink an {@code invokedynamic} instruction bound to a {@code ConstantCallSite} is
* to invalidate the instruction as a whole.
* @author John Rose, JSR 292 EG
*/
public class ConstantCallSite extends CallSite {
/** Create a call site with a permanent target. */
public ConstantCallSite(MethodHandle target) {
super(target);
}
/** Throw an {@link IllegalArgumentException}, because this kind of call site cannot change its target. */
@Override public final void setTarget(MethodHandle ignore) {
throw new IllegalArgumentException("ConstantCallSite");
}
}
...@@ -35,7 +35,7 @@ package java.dyn; ...@@ -35,7 +35,7 @@ package java.dyn;
* The target method is a property of the reified {@linkplain CallSite call site object} * The target method is a property of the reified {@linkplain CallSite call site object}
* which is linked to each active {@code invokedynamic} instruction. * which is linked to each active {@code invokedynamic} instruction.
* The call site object is initially produced by a * The call site object is initially produced by a
* {@linkplain java.dyn.Linkage#registerBootstrapMethod(Class, MethodHandle) bootstrap method} * {@linkplain BootstrapMethod bootstrap method}
* associated with the class whose bytecodes include the dynamic call site. * associated with the class whose bytecodes include the dynamic call site.
* <p> * <p>
* The type {@code InvokeDynamic} has no particular meaning as a * The type {@code InvokeDynamic} has no particular meaning as a
...@@ -45,22 +45,31 @@ package java.dyn; ...@@ -45,22 +45,31 @@ package java.dyn;
* It may be imported for ease of use. * It may be imported for ease of use.
* <p> * <p>
* Here are some examples: * Here are some examples:
* <p><blockquote><pre> <blockquote><pre><!-- see indy-demo/src/JavaDocExamples.java -->
* Object x; String s; int i; &#064;BootstrapMethod(value=Here.class, name="bootstrapDynamic")
* x = InvokeDynamic.greet("world"); // greet(Ljava/lang/String;)Ljava/lang/Object; static void example() throws Throwable {
* s = InvokeDynamic.&lt;String&gt;hail(x); // hail(Ljava/lang/Object;)Ljava/lang/String; Object x; String s; int i;
* InvokeDynamic.&lt;void&gt;cogito(); // cogito()V x = InvokeDynamic.greet("world"); // greet(Ljava/lang/String;)Ljava/lang/Object;
* i = InvokeDynamic.&lt;int&gt;#"op:+"(2, 3); // "op:+"(II)I s = (String) InvokeDynamic.hail(x); // hail(Ljava/lang/Object;)Ljava/lang/String;
* </pre></blockquote> InvokeDynamic.cogito(); // cogito()V
i = (int) InvokeDynamic.#"op:+"(2, 3); // "op:+"(II)I
}
static MethodHandle bootstrapDynamic(Class caller, String name, MethodType type) { ... }
</pre></blockquote>
* Each of the above calls generates a single invokedynamic instruction * Each of the above calls generates a single invokedynamic instruction
* with the name-and-type descriptors indicated in the comments. * with the name-and-type descriptors indicated in the comments.
* <p>
* The argument types are taken directly from the actual arguments, * The argument types are taken directly from the actual arguments,
* while the return type is taken from the type parameter. * while the return type corresponds to the target of the assignment.
* (This type parameter may be a primtive, and it defaults to {@code Object}.) * (Currently, the return type must be given as a false type parameter.
* This type parameter is an irregular use of the generic type syntax,
* and is likely to change in favor of a convention based on target typing.)
* <p>
* The final example uses a special syntax for uttering non-Java names. * The final example uses a special syntax for uttering non-Java names.
* Any name legal to the JVM may be given between the double quotes. * Any name legal to the JVM may be given between the double quotes.
* <p>
* None of these calls is complete without a bootstrap method, * None of these calls is complete without a bootstrap method,
* which must be registered by the static initializer of the enclosing class. * which must be declared for the enclosing class or method.
* @author John Rose, JSR 292 EG * @author John Rose, JSR 292 EG
*/ */
@MethodHandle.PolymorphicSignature @MethodHandle.PolymorphicSignature
......
...@@ -28,15 +28,11 @@ package java.dyn; ...@@ -28,15 +28,11 @@ package java.dyn;
/** /**
* Thrown to indicate that an {@code invokedynamic} instruction has * Thrown to indicate that an {@code invokedynamic} instruction has
* failed to find its * failed to find its
* {@linkplain Linkage#registerBootstrapMethod(Class, MethodHandle) bootstrap method}, * {@linkplain BootstrapMethod bootstrap method},
* or the bootstrap method has * or the bootstrap method has
* failed to provide a * failed to provide a
* {@linkplain CallSite} call site with a non-null {@linkplain MethodHandle target} * {@linkplain CallSite} call site with a non-null {@linkplain MethodHandle target}
* of the correct {@linkplain MethodType method type}. * of the correct {@linkplain MethodType method type}.
* <p>
* The bootstrap method must have been declared during a class's initialization
* by a call to one of the overloadings of
* {@link Linkage#registerBootstrapMethod registerBootstrapMethod}.
* *
* @author John Rose, JSR 292 EG * @author John Rose, JSR 292 EG
* @since 1.7 * @since 1.7
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
package java.dyn; package java.dyn;
import java.lang.annotation.Annotation;
import java.dyn.MethodHandles.Lookup; import java.dyn.MethodHandles.Lookup;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import sun.dyn.Access; import sun.dyn.Access;
...@@ -56,11 +55,7 @@ public class Linkage { ...@@ -56,11 +55,7 @@ public class Linkage {
* <li>the class containing the {@code invokedynamic} instruction, for which the bootstrap method was registered * <li>the class containing the {@code invokedynamic} instruction, for which the bootstrap method was registered
* <li>the name of the method being invoked (a {@link String}) * <li>the name of the method being invoked (a {@link String})
* <li>the type of the method being invoked (a {@link MethodType}) * <li>the type of the method being invoked (a {@link MethodType})
* <li><em>TBD</em> optionally, an unordered array of {@link Annotation}s attached to the call site
* <em>(Until this feature is implemented, this will always receive an empty array.)</em>
* </ul> * </ul>
* <em>(TBD: The final argument type may be missing from the method handle's type.
* Additional arguments may be added in the future.)</em>
* The bootstrap method acts as a factory method which accepts the given arguments * The bootstrap method acts as a factory method which accepts the given arguments
* and returns a {@code CallSite} object (possibly of a subclass of {@code CallSite}). * and returns a {@code CallSite} object (possibly of a subclass of {@code CallSite}).
* <p> * <p>
...@@ -86,6 +81,7 @@ public class Linkage { ...@@ -86,6 +81,7 @@ public class Linkage {
* or is already running in another thread * or is already running in another thread
* @exception SecurityException if there is a security manager installed, * @exception SecurityException if there is a security manager installed,
* and a {@link LinkagePermission} check fails for "registerBootstrapMethod" * and a {@link LinkagePermission} check fails for "registerBootstrapMethod"
* @deprecated Use @{@link BootstrapMethod} annotations instead
*/ */
public static public static
void registerBootstrapMethod(Class callerClass, MethodHandle bootstrapMethod) { void registerBootstrapMethod(Class callerClass, MethodHandle bootstrapMethod) {
...@@ -97,14 +93,9 @@ public class Linkage { ...@@ -97,14 +93,9 @@ public class Linkage {
static private void checkBSM(MethodHandle mh) { static private void checkBSM(MethodHandle mh) {
if (mh == null) throw newIllegalArgumentException("null bootstrap method"); if (mh == null) throw newIllegalArgumentException("null bootstrap method");
if (mh.type() == BOOTSTRAP_METHOD_TYPE_2)
// For now, always pass an empty array for the Annotations argument
mh = MethodHandles.insertArguments(mh, BOOTSTRAP_METHOD_TYPE_2.parameterCount()-1,
(Object)NO_ANNOTATIONS);
if (mh.type() == BOOTSTRAP_METHOD_TYPE) return; if (mh.type() == BOOTSTRAP_METHOD_TYPE) return;
throw new WrongMethodTypeException(mh.toString()); throw new WrongMethodTypeException(mh.toString());
} }
static private final Annotation[] NO_ANNOTATIONS = { };
/** /**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em> * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
...@@ -115,6 +106,7 @@ public class Linkage { ...@@ -115,6 +106,7 @@ public class Linkage {
* @throws NoSuchMethodException if there is no such method * @throws NoSuchMethodException if there is no such method
* @throws IllegalStateException if the caller class's static initializer * @throws IllegalStateException if the caller class's static initializer
* has already run, or is already running in another thread * has already run, or is already running in another thread
* @deprecated Use @{@link BootstrapMethod} annotations instead
*/ */
public static public static
void registerBootstrapMethod(Class<?> runtime, String name) { void registerBootstrapMethod(Class<?> runtime, String name) {
...@@ -131,6 +123,7 @@ public class Linkage { ...@@ -131,6 +123,7 @@ public class Linkage {
* @throws IllegalArgumentException if there is no such method * @throws IllegalArgumentException if there is no such method
* @throws IllegalStateException if the caller class's static initializer * @throws IllegalStateException if the caller class's static initializer
* has already run, or is already running in another thread * has already run, or is already running in another thread
* @deprecated Use @{@link BootstrapMethod} annotations instead
*/ */
public static public static
void registerBootstrapMethod(String name) { void registerBootstrapMethod(String name) {
...@@ -142,18 +135,10 @@ public class Linkage { ...@@ -142,18 +135,10 @@ public class Linkage {
void registerBootstrapMethodLookup(Class<?> callerClass, Class<?> runtime, String name) { void registerBootstrapMethodLookup(Class<?> callerClass, Class<?> runtime, String name) {
Lookup lookup = new Lookup(IMPL_TOKEN, callerClass); Lookup lookup = new Lookup(IMPL_TOKEN, callerClass);
MethodHandle bootstrapMethod; MethodHandle bootstrapMethod;
// Try both types. TBD
try { try {
bootstrapMethod = lookup.findStatic(runtime, name, BOOTSTRAP_METHOD_TYPE_2); bootstrapMethod = lookup.findStatic(runtime, name, BOOTSTRAP_METHOD_TYPE);
} catch (NoAccessException ex) { } catch (NoAccessException ex) {
bootstrapMethod = null; throw new IllegalArgumentException("no such bootstrap method in "+runtime+": "+name, ex);
}
if (bootstrapMethod == null) {
try {
bootstrapMethod = lookup.findStatic(runtime, name, BOOTSTRAP_METHOD_TYPE);
} catch (NoAccessException ex) {
throw new IllegalArgumentException("no such bootstrap method in "+runtime+": "+name, ex);
}
} }
checkBSM(bootstrapMethod); checkBSM(bootstrapMethod);
MethodHandleImpl.registerBootstrap(IMPL_TOKEN, callerClass, bootstrapMethod); MethodHandleImpl.registerBootstrap(IMPL_TOKEN, callerClass, bootstrapMethod);
...@@ -172,6 +157,7 @@ public class Linkage { ...@@ -172,6 +157,7 @@ public class Linkage {
* and the immediate caller of this method is not in the same * and the immediate caller of this method is not in the same
* package as the caller class * package as the caller class
* and a {@link LinkagePermission} check fails for "getBootstrapMethod" * and a {@link LinkagePermission} check fails for "getBootstrapMethod"
* @deprecated
*/ */
public static public static
MethodHandle getBootstrapMethod(Class callerClass) { MethodHandle getBootstrapMethod(Class callerClass) {
...@@ -188,10 +174,6 @@ public class Linkage { ...@@ -188,10 +174,6 @@ public class Linkage {
public static final MethodType BOOTSTRAP_METHOD_TYPE public static final MethodType BOOTSTRAP_METHOD_TYPE
= MethodType.methodType(CallSite.class, = MethodType.methodType(CallSite.class,
Class.class, String.class, MethodType.class); Class.class, String.class, MethodType.class);
static final MethodType BOOTSTRAP_METHOD_TYPE_2
= MethodType.methodType(CallSite.class,
Class.class, String.class, MethodType.class,
Annotation[].class);
/** /**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em> * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
......
...@@ -31,6 +31,7 @@ import java.util.Hashtable; ...@@ -31,6 +31,7 @@ import java.util.Hashtable;
import java.util.StringTokenizer; import java.util.StringTokenizer;
/** /**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* This class is for managing runtime permission checking for * This class is for managing runtime permission checking for
* operations performed by methods in the {@link Linkage} class. * operations performed by methods in the {@link Linkage} class.
* Like a {@link RuntimePermission}, on which it is modeled, * Like a {@link RuntimePermission}, on which it is modeled,
...@@ -52,13 +53,6 @@ import java.util.StringTokenizer; ...@@ -52,13 +53,6 @@ import java.util.StringTokenizer;
* </tr> * </tr>
* *
* <tr> * <tr>
* <td>registerBootstrapMethod.{class name}</td>
* <td>Specifying a bootstrap method for {@code invokedynamic} instructions within a class of the given name</td>
* <td>An attacker could attempt to attach a bootstrap method to a class which
* has just been loaded, thus gaining control of its {@code invokedynamic} calls.</td>
* </tr>
*
* <tr>
* <td>invalidateAll</td> * <td>invalidateAll</td>
* <td>Force the relinking of invokedynamic call sites everywhere.</td> * <td>Force the relinking of invokedynamic call sites everywhere.</td>
* <td>This could allow an attacker to slow down the system, * <td>This could allow an attacker to slow down the system,
...@@ -73,8 +67,9 @@ import java.util.StringTokenizer; ...@@ -73,8 +67,9 @@ import java.util.StringTokenizer;
* <td>See {@code invalidateAll}.</td> * <td>See {@code invalidateAll}.</td>
* </tr> * </tr>
* </table> * </table>
* <p>ISSUE: Is this still needed?
* *
* @see java.security.RuntimePermission * @see java.lang.RuntimePermission
* @see java.lang.SecurityManager * @see java.lang.SecurityManager
* *
* @author John Rose, JSR 292 EG * @author John Rose, JSR 292 EG
...@@ -86,7 +81,7 @@ public final class LinkagePermission extends BasicPermission { ...@@ -86,7 +81,7 @@ public final class LinkagePermission extends BasicPermission {
/** /**
* Create a new LinkagePermission with the given name. * Create a new LinkagePermission with the given name.
* The name is the symbolic name of the LinkagePermission, such as * The name is the symbolic name of the LinkagePermission, such as
* "registerBootstrapMethod", "invalidateCallerClass.*", etc. An asterisk * "invalidateCallerClass.*", etc. An asterisk
* may appear at the end of the name, following a ".", or by itself, to * may appear at the end of the name, following a ".", or by itself, to
* signify a wildcard match. * signify a wildcard match.
* *
......
/* /*
* Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2008, 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
...@@ -36,11 +36,13 @@ import static sun.dyn.MemberName.newIllegalArgumentException; // utility ...@@ -36,11 +36,13 @@ import static sun.dyn.MemberName.newIllegalArgumentException; // utility
/** /**
* A method handle is a typed, directly executable reference to a method, * A method handle is a typed, directly executable reference to a method,
* constructor, field, or similar low-level operation, with optional * constructor, field, or similar low-level operation, with optional
* conversion or substitution of arguments or return values. * transformations of arguments or return values.
* (These transformations include conversion, insertion, deletion,
* substitution. See the methods of this class and of {@link MethodHandles}.)
* <p> * <p>
* Method handles are strongly typed according to signature. * Method handles are strongly typed according to signature.
* They are not distinguished by method name or enclosing class. * They are not distinguished by method name or enclosing class.
* A method handle must be invoked under a signature which exactly matches * A method handle must be invoked under a signature which matches
* the method handle's own {@link MethodType method type}. * the method handle's own {@link MethodType method type}.
* <p> * <p>
* Every method handle confesses its type via the {@code type} accessor. * Every method handle confesses its type via the {@code type} accessor.
...@@ -174,9 +176,10 @@ assert(i == 3); ...@@ -174,9 +176,10 @@ assert(i == 3);
* merely a documentation convention. These type parameters do * merely a documentation convention. These type parameters do
* not play a role in type-checking method handle invocations. * not play a role in type-checking method handle invocations.
* <p> * <p>
* Note: Like classes and strings, method handles that correspond directly * Like classes and strings, method handles that correspond to accessible
* to fields and methods can be represented directly as constants to be * fields, methods, and constructors can be represented directly
* loaded by {@code ldc} bytecodes. * in a class file's constant pool as constants to be loaded by {@code ldc} bytecodes.
* Loading such a constant causes the component classes of its type to be loaded as necessary.
* *
* @see MethodType * @see MethodType
* @see MethodHandles * @see MethodHandles
...@@ -186,6 +189,7 @@ public abstract class MethodHandle ...@@ -186,6 +189,7 @@ public abstract class MethodHandle
// Note: This is an implementation inheritance hack, and will be removed // Note: This is an implementation inheritance hack, and will be removed
// with a JVM change which moves the required hidden state onto this class. // with a JVM change which moves the required hidden state onto this class.
extends MethodHandleImpl extends MethodHandleImpl
implements MethodHandleProvider
{ {
private static Access IMPL_TOKEN = Access.getToken(); private static Access IMPL_TOKEN = Access.getToken();
...@@ -197,7 +201,7 @@ public abstract class MethodHandle ...@@ -197,7 +201,7 @@ public abstract class MethodHandle
* those methods which are signature polymorphic. * those methods which are signature polymorphic.
*/ */
@java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD,java.lang.annotation.ElementType.TYPE}) @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD,java.lang.annotation.ElementType.TYPE})
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@interface PolymorphicSignature { } @interface PolymorphicSignature { }
private MethodType type; private MethodType type;
...@@ -274,10 +278,14 @@ public abstract class MethodHandle ...@@ -274,10 +278,14 @@ public abstract class MethodHandle
* and performing simple conversions for arguments and return types. * and performing simple conversions for arguments and return types.
* The signature at the call site of {@code invokeGeneric} must * The signature at the call site of {@code invokeGeneric} must
* have the same arity as this method handle's {@code type}. * have the same arity as this method handle's {@code type}.
* The same conversions are allowed on arguments or return values as are supported by * <p>
* by {@link MethodHandles#convertArguments}.
* If the call site signature exactly matches this method handle's {@code type}, * If the call site signature exactly matches this method handle's {@code type},
* the call proceeds as if by {@link #invokeExact}. * the call proceeds as if by {@link #invokeExact}.
* <p>
* Otherwise, the call proceeds as if this method handle were first
* adjusted by calling {@link #asType} to adjust this method handle
* to the required type, and then the call proceeds as if by
* {@link #invokeExact} on the adjusted method handle.
*/ */
public final native @PolymorphicSignature <R,A> R invokeGeneric(A... args) throws Throwable; public final native @PolymorphicSignature <R,A> R invokeGeneric(A... args) throws Throwable;
...@@ -538,4 +546,10 @@ public abstract class MethodHandle ...@@ -538,4 +546,10 @@ public abstract class MethodHandle
public final MethodHandle bindTo(Object x) { public final MethodHandle bindTo(Object x) {
return MethodHandles.insertArguments(this, 0, x); return MethodHandles.insertArguments(this, 0, x);
} }
/** Implementation of {@link MethodHandleProvider}, which returns {@code this}. */
public final MethodHandle asMethodHandle() { return this; }
/** Implementation of {@link MethodHandleProvider}, which returns {@code this.asType(type)}. */
public final MethodHandle asMethodHandle(MethodType type) { return this.asType(type); }
} }
/*
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. 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.dyn;
/**
* An interface for an object to provide a target {@linkplain MethodHandle method handle} to a {@code invokedynamic} instruction.
* There are many function-like objects in various Java APIs.
* This interface provides a standard way for such function-like objects to be bound
* to a dynamic call site, by providing a view of their behavior in the form of a low-level method handle.
* <p>
* The type {@link MethodHandle} is a concrete class whose implementation
* hierarchy (if any) may be tightly coupled to the underlying JVM implementation.
* It cannot also serve as a base type for user-defined functional APIs.
* For this reason, {@code MethodHandle} cannot be subclassed to add new
* behavior to method handles. But this interface can be used to provide
* a link between a user-defined function and the {@code invokedynamic}
* instruction and the method handle API.
*/
public interface MethodHandleProvider {
/** Produce a method handle which will serve as a behavioral proxy for the current object.
* The type and invocation behavior of the proxy method handle are user-defined,
* and should have some relation to the intended meaning of the original object itself.
* <p>
* The current object may have a changeable behavior.
* For example, {@link CallSite} has a {@code setTarget} method which changes its invocation.
* In such a case, it is <em>incorrect</em> for {@code asMethodHandle} to return
* a method handle whose behavior may diverge from that of the current object.
* Rather, the returned method handle must stably and permanently access
* the behavior of the current object, even if that behavior is changeable.
* <p>
* The reference identity of the proxy method handle is not guaranteed to
* have any particular relation to the reference identity of the object.
* In particular, several objects with the same intended meaning could
* share a common method handle, or the same object could return different
* method handles at different times. In the latter case, the different
* method handles should have the same type and invocation behavior,
* and be usable from any thread at any time.
* In particular, if a MethodHandleProvider is bound to an <code>invokedynamic</code>
* call site, the proxy method handle extracted at the time of binding
* will be used for an unlimited time, until the call site is rebound.
* <p>
* The type {@link MethodHandle} itself implements {@code MethodHandleProvider}, and
* for this method simply returns {@code this}.
*/
public MethodHandle asMethodHandle();
/** Produce a method handle of a given type which will serve as a behavioral proxy for the current object.
* As for the no-argument version {@link #asMethodHandle()}, the invocation behavior of the
* proxy method handle is user-defined. But the type must be the given type,
* or else a {@link WrongMethodTypeException} must be thrown.
* <p>
* If the current object somehow represents a variadic or overloaded behavior,
* the method handle returned for a given type might represent only a subset of
* the current object's repertoire of behaviors, which correspond to that type.
*/
public MethodHandle asMethodHandle(MethodType type) throws WrongMethodTypeException;
}
...@@ -25,15 +25,12 @@ ...@@ -25,15 +25,12 @@
package java.dyn; package java.dyn;
import java.lang.reflect.Constructor; import java.lang.reflect.*;
import sun.dyn.Access; import sun.dyn.Access;
import sun.dyn.MemberName; import sun.dyn.MemberName;
import sun.dyn.MethodHandleImpl; import sun.dyn.MethodHandleImpl;
import sun.dyn.util.VerifyAccess; import sun.dyn.util.VerifyAccess;
import sun.dyn.util.Wrapper; import sun.dyn.util.Wrapper;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List; import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
...@@ -81,6 +78,14 @@ public class MethodHandles { ...@@ -81,6 +78,14 @@ public class MethodHandles {
* Return a {@link Lookup lookup object} which is trusted minimally. * Return a {@link Lookup lookup object} which is trusted minimally.
* It can only be used to create method handles to * It can only be used to create method handles to
* publicly accessible fields and methods. * publicly accessible fields and methods.
* <p>
* As a matter of pure convention, the {@linkplain Lookup#lookupClass lookup class}
* of this lookup object will be {@link java.lang.Object}.
* <p>
* The lookup class can be changed to any other class {@code C} using an expression of the form
* {@linkplain Lookup#in <code>publicLookup().in(C.class)</code>}.
* Since all classes have equal access to public names,
* such a change would confer no new access rights.
*/ */
public static Lookup publicLookup() { public static Lookup publicLookup() {
return Lookup.PUBLIC_LOOKUP; return Lookup.PUBLIC_LOOKUP;
...@@ -90,9 +95,10 @@ public class MethodHandles { ...@@ -90,9 +95,10 @@ public class MethodHandles {
* A <em>lookup object</em> is a factory for creating method handles, * A <em>lookup object</em> is a factory for creating method handles,
* when the creation requires access checking. * when the creation requires access checking.
* Method handles do not perform * Method handles do not perform
* access checks when they are called; this is a major difference * access checks when they are called, but rather when they are created.
* (This is a major difference
* from reflective {@link Method}, which performs access checking * from reflective {@link Method}, which performs access checking
* against every caller, on every call. * against every caller, on every call.)
* Therefore, method handle access * Therefore, method handle access
* restrictions must be enforced when a method handle is created. * restrictions must be enforced when a method handle is created.
* The caller class against which those restrictions are enforced * The caller class against which those restrictions are enforced
...@@ -107,7 +113,7 @@ public class MethodHandles { ...@@ -107,7 +113,7 @@ public class MethodHandles {
* It may then use this factory to create method handles on * It may then use this factory to create method handles on
* all of its methods, including private ones. * all of its methods, including private ones.
* It may also delegate the lookup (e.g., to a metaobject protocol) * It may also delegate the lookup (e.g., to a metaobject protocol)
* by passing the {@code Lookup} object to other code. * by passing the lookup object to other code.
* If this other code creates method handles, they will be access * If this other code creates method handles, they will be access
* checked against the original lookup class, and not with any higher * checked against the original lookup class, and not with any higher
* privileges. * privileges.
...@@ -125,23 +131,28 @@ public class MethodHandles { ...@@ -125,23 +131,28 @@ public class MethodHandles {
* It can also fail if a security manager is installed and refuses * It can also fail if a security manager is installed and refuses
* access. In any of these cases, an exception will be * access. In any of these cases, an exception will be
* thrown from the attempted lookup. * thrown from the attempted lookup.
* <p>
* In general, the conditions under which a method handle may be * In general, the conditions under which a method handle may be
* created for a method {@code M} are exactly as restrictive as the conditions * created for a method {@code M} are exactly as restrictive as the conditions
* under which the lookup class could have compiled a call to {@code M}. * under which the lookup class could have compiled a call to {@code M}.
* At least some of these error conditions are likely to be * This rule is applied even if the Java compiler might have created
* represented by checked exceptions in the final version of this API. * an wrapper method to access a private method of another class
* in the same top-level declaration.
* For example, a lookup object created for a nested class {@code C.D}
* can access private members within other related classes such as
* {@code C}, {@code C.D.E}, or {@code C.B}.
*/ */
public static final public static final
class Lookup { class Lookup {
/** The class on behalf of whom the lookup is being performed. */ /** The class on behalf of whom the lookup is being performed. */
private final Class<?> lookupClass; private final Class<?> lookupClass;
/** The allowed sorts of members which may be looked up (public, etc.), with STRICT for package. */ /** The allowed sorts of members which may be looked up (public, etc.), with STATIC for package. */
private final int allowedModes; private final int allowedModes;
private static final int private static final int
PUBLIC = Modifier.PUBLIC, PUBLIC = Modifier.PUBLIC,
PACKAGE = Modifier.STRICT, PACKAGE = Modifier.STATIC,
PROTECTED = Modifier.PROTECTED, PROTECTED = Modifier.PROTECTED,
PRIVATE = Modifier.PRIVATE, PRIVATE = Modifier.PRIVATE,
ALL_MODES = (PUBLIC | PACKAGE | PROTECTED | PRIVATE), ALL_MODES = (PUBLIC | PACKAGE | PROTECTED | PRIVATE),
...@@ -155,8 +166,10 @@ public class MethodHandles { ...@@ -155,8 +166,10 @@ public class MethodHandles {
/** Which class is performing the lookup? It is this class against /** Which class is performing the lookup? It is this class against
* which checks are performed for visibility and access permissions. * which checks are performed for visibility and access permissions.
* <p> * <p>
* This value is null if and only if this lookup was produced * The class implies a maximum level of access permission,
* by {@link MethodHandles#publicLookup}. * but the permissions may be additionally limited by the bitmask
* {@link #lookupModes}, which controls whether non-public members
* can be accessed.
*/ */
public Class<?> lookupClass() { public Class<?> lookupClass() {
return lookupClass; return lookupClass;
...@@ -168,10 +181,15 @@ public class MethodHandles { ...@@ -168,10 +181,15 @@ public class MethodHandles {
} }
/** Which types of members can this lookup object produce? /** Which types of members can this lookup object produce?
* The result is a bit-mask of the modifier bits PUBLIC, PROTECTED, PRIVATE, and STRICT. * The result is a bit-mask of the {@link Modifier} bits
* The modifier bit STRICT stands in for the (non-existent) package protection mode. * {@linkplain Modifier#PUBLIC PUBLIC (0x01)},
* {@linkplain Modifier#PROTECTED PROTECTED (0x02)},
* {@linkplain Modifier#PRIVATE PRIVATE (0x04)},
* and {@linkplain Modifier#STATIC STATIC (0x08)}.
* The modifier bit {@code STATIC} stands in for the package protection mode,
* which does not have an explicit modifier bit.
*/ */
int lookupModes() { public int lookupModes() {
return allowedModes & ALL_MODES; return allowedModes & ALL_MODES;
} }
...@@ -621,32 +639,32 @@ public class MethodHandles { ...@@ -621,32 +639,32 @@ public class MethodHandles {
/// Helper methods, all package-private. /// Helper methods, all package-private.
MemberName resolveOrFail(Class<?> refc, String name, Class<?> type, boolean isStatic) { MemberName resolveOrFail(Class<?> refc, String name, Class<?> type, boolean isStatic) throws NoAccessException {
checkSymbolicClass(refc); // do this before attempting to resolve checkSymbolicClass(refc); // do this before attempting to resolve
int mods = (isStatic ? Modifier.STATIC : 0); int mods = (isStatic ? Modifier.STATIC : 0);
return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull()); return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull());
} }
MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic) { MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic) throws NoAccessException {
checkSymbolicClass(refc); // do this before attempting to resolve checkSymbolicClass(refc); // do this before attempting to resolve
int mods = (isStatic ? Modifier.STATIC : 0); int mods = (isStatic ? Modifier.STATIC : 0);
return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull()); return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull());
} }
MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic, MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic,
boolean searchSupers, Class<?> specialCaller) { boolean searchSupers, Class<?> specialCaller) throws NoAccessException {
checkSymbolicClass(refc); // do this before attempting to resolve checkSymbolicClass(refc); // do this before attempting to resolve
int mods = (isStatic ? Modifier.STATIC : 0); int mods = (isStatic ? Modifier.STATIC : 0);
return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), searchSupers, specialCaller); return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), searchSupers, specialCaller);
} }
void checkSymbolicClass(Class<?> refc) { void checkSymbolicClass(Class<?> refc) throws NoAccessException {
Class<?> caller = lookupClassOrNull(); Class<?> caller = lookupClassOrNull();
if (caller != null && !VerifyAccess.isClassAccessible(refc, caller)) if (caller != null && !VerifyAccess.isClassAccessible(refc, caller))
throw newNoAccessException("symbolic reference class is not public", new MemberName(refc), caller); throw newNoAccessException("symbolic reference class is not public", new MemberName(refc), caller);
} }
void checkMethod(Class<?> refc, MemberName m, boolean wantStatic) { void checkMethod(Class<?> refc, MemberName m, boolean wantStatic) throws NoAccessException {
String message; String message;
if (m.isConstructor()) if (m.isConstructor())
message = "expected a method, not a constructor"; message = "expected a method, not a constructor";
...@@ -659,7 +677,7 @@ public class MethodHandles { ...@@ -659,7 +677,7 @@ public class MethodHandles {
throw newNoAccessException(message, m, lookupClass()); throw newNoAccessException(message, m, lookupClass());
} }
void checkAccess(Class<?> refc, MemberName m) { void checkAccess(Class<?> refc, MemberName m) throws NoAccessException {
int allowedModes = this.allowedModes; int allowedModes = this.allowedModes;
if (allowedModes == TRUSTED) return; if (allowedModes == TRUSTED) return;
int mods = m.getModifiers(); int mods = m.getModifiers();
...@@ -695,14 +713,14 @@ public class MethodHandles { ...@@ -695,14 +713,14 @@ public class MethodHandles {
return "member is private to package"; return "member is private to package";
} }
void checkSpecialCaller(Class<?> specialCaller) { void checkSpecialCaller(Class<?> specialCaller) throws NoAccessException {
if (allowedModes == TRUSTED) return; if (allowedModes == TRUSTED) return;
if (!VerifyAccess.isSamePackageMember(specialCaller, lookupClass())) if (!VerifyAccess.isSamePackageMember(specialCaller, lookupClass()))
throw newNoAccessException("no private access for invokespecial", throw newNoAccessException("no private access for invokespecial",
new MemberName(specialCaller), lookupClass()); new MemberName(specialCaller), lookupClass());
} }
MethodHandle restrictProtectedReceiver(MemberName method, MethodHandle mh) { MethodHandle restrictProtectedReceiver(MemberName method, MethodHandle mh) throws NoAccessException {
// The accessing class only has the right to use a protected member // The accessing class only has the right to use a protected member
// on itself or a subclass. Enforce that restriction, from JVMS 5.4.4, etc. // on itself or a subclass. Enforce that restriction, from JVMS 5.4.4, etc.
if (!method.isProtected() || method.isStatic() if (!method.isProtected() || method.isStatic()
...@@ -712,7 +730,7 @@ public class MethodHandles { ...@@ -712,7 +730,7 @@ public class MethodHandles {
else else
return restrictReceiver(method, mh, lookupClass()); return restrictReceiver(method, mh, lookupClass());
} }
MethodHandle restrictReceiver(MemberName method, MethodHandle mh, Class<?> caller) { MethodHandle restrictReceiver(MemberName method, MethodHandle mh, Class<?> caller) throws NoAccessException {
assert(!method.isStatic()); assert(!method.isStatic());
Class<?> defc = method.getDeclaringClass(); // receiver type of mh is too wide Class<?> defc = method.getDeclaringClass(); // receiver type of mh is too wide
if (defc.isInterface() || !defc.isAssignableFrom(caller)) { if (defc.isInterface() || !defc.isAssignableFrom(caller)) {
...@@ -898,11 +916,16 @@ public class MethodHandles { ...@@ -898,11 +916,16 @@ public class MethodHandles {
* @return a method handle which always invokes the call site's target * @return a method handle which always invokes the call site's target
*/ */
public static public static
MethodHandle dynamicInvoker(CallSite site) { MethodHandle dynamicInvoker(CallSite site) throws NoAccessException {
MethodHandle getCSTarget = GET_TARGET; MethodHandle getCSTarget = GET_TARGET;
if (getCSTarget == null) if (getCSTarget == null) {
GET_TARGET = getCSTarget = Lookup.IMPL_LOOKUP. try {
findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class)); GET_TARGET = getCSTarget = Lookup.IMPL_LOOKUP.
findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
} catch (NoAccessException ex) {
throw new InternalError();
}
}
MethodHandle getTarget = MethodHandleImpl.bindReceiver(IMPL_TOKEN, getCSTarget, site); MethodHandle getTarget = MethodHandleImpl.bindReceiver(IMPL_TOKEN, getCSTarget, site);
MethodHandle invoker = exactInvoker(site.type()); MethodHandle invoker = exactInvoker(site.type());
return foldArguments(invoker, getTarget); return foldArguments(invoker, getTarget);
...@@ -1260,17 +1283,20 @@ public class MethodHandles { ...@@ -1260,17 +1283,20 @@ public class MethodHandles {
* <p> * <p>
* <b>Example:</b> * <b>Example:</b>
* <p><blockquote><pre> * <p><blockquote><pre>
* MethodHandle cat = MethodHandles.lookup(). * import static java.dyn.MethodHandles.*;
* findVirtual(String.class, "concat", String.class, String.class); * import static java.dyn.MethodType.*;
* System.out.println(cat.&lt;String&gt;invokeExact("x", "y")); // xy * ...
* MethodHandle cat = lookup().findVirtual(String.class,
* "concat", methodType(String.class, String.class));
* System.out.println((String) cat.invokeExact("x", "y")); // xy
* MethodHandle d0 = dropArguments(cat, 0, String.class); * MethodHandle d0 = dropArguments(cat, 0, String.class);
* System.out.println(d0.&lt;String&gt;invokeExact("x", "y", "z")); // xy * System.out.println((String) d0.invokeExact("x", "y", "z")); // yz
* MethodHandle d1 = dropArguments(cat, 1, String.class); * MethodHandle d1 = dropArguments(cat, 1, String.class);
* System.out.println(d1.&lt;String&gt;invokeExact("x", "y", "z")); // xz * System.out.println((String) d1.invokeExact("x", "y", "z")); // xz
* MethodHandle d2 = dropArguments(cat, 2, String.class); * MethodHandle d2 = dropArguments(cat, 2, String.class);
* System.out.println(d2.&lt;String&gt;invokeExact("x", "y", "z")); // yz * System.out.println((String) d2.invokeExact("x", "y", "z")); // xy
* MethodHandle d12 = dropArguments(cat, 1, String.class, String.class); * MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
* System.out.println(d12.&lt;String&gt;invokeExact("w", "x", "y", "z")); // wz * System.out.println((String) d12.invokeExact("x", 12, true, "z")); // xz
* </pre></blockquote> * </pre></blockquote>
* @param target the method handle to invoke after the argument is dropped * @param target the method handle to invoke after the argument is dropped
* @param valueTypes the type(s) of the argument to drop * @param valueTypes the type(s) of the argument to drop
...@@ -1562,4 +1588,107 @@ public class MethodHandles { ...@@ -1562,4 +1588,107 @@ public class MethodHandles {
MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType) { MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType) {
return MethodHandleImpl.throwException(IMPL_TOKEN, MethodType.methodType(returnType, exType)); return MethodHandleImpl.throwException(IMPL_TOKEN, MethodType.methodType(returnType, exType));
} }
/**
* Produce a wrapper instance of the given "SAM" type which redirects its calls to the given method handle.
* A SAM type is a type which declares a single abstract method.
* Additionally, it must have either no constructor (as an interface)
* or have a public or protected constructor of zero arguments (as a class).
* <p>
* The resulting instance of the required SAM type will respond to
* invocation of the SAM type's single abstract method by calling
* the given {@code target} on the incoming arguments,
* and returning or throwing whatever the {@code target}
* returns or throws. The invocation will be as if by
* {@code target.invokeExact}.
* <p>
* The method handle may throw an <em>undeclared exception</em>,
* which means any checked exception (or other checked throwable)
* not declared by the SAM type's single abstract method.
* If this happens, the throwable will be wrapped in an instance
* of {@link UndeclaredThrowableException} and thrown in that
* wrapped form.
* <p>
* The wrapper instance is guaranteed to be of a non-public
* implementation class C in a package containing no classes
* or methods except system-defined classes and methods.
* The implementation class C will have no public supertypes
* or public methods beyond the following:
* <ul>
* <li>the SAM type itself and any methods in the SAM type
* <li>the supertypes of the SAM type (if any) and their methods
* <li>{@link Object} and its methods
* <li>{@link MethodHandleProvider} and its methods
* </ul>
* <p>
* No stable mapping is promised between the SAM type and
* the implementation class C. Over time, several implementation
* classes might be used for the same SAM type.
* <p>
* This method is not guaranteed to return a distinct
* wrapper object for each separate call. If the JVM is able
* to prove that a wrapper has already been created for a given
* method handle, or for another method handle with the
* same behavior, the JVM may return that wrapper in place of
* a new wrapper.
* @param target the method handle to invoke from the wrapper
* @param samType the desired type of the wrapper, a SAM type
* @return a correctly-typed wrapper for the given {@code target}
* @throws IllegalArgumentException if the {@code target} throws
* an undeclared exception
*/
// ISSUE: Should we delegate equals/hashCode to the targets?
// Not useful unless there is a stable equals/hashCode behavior
// for MethodHandle, and for MethodHandleProvider.asMethodHandle.
public static
<T> T asInstance(MethodHandle target, Class<T> samType) {
// POC implementation only; violates the above contract several ways
final Method sam = getSamMethod(samType);
if (sam == null)
throw new IllegalArgumentException("not a SAM type: "+samType.getName());
MethodType samMT = MethodType.methodType(sam.getReturnType(), sam.getParameterTypes());
if (!samMT.equals(target.type()))
throw new IllegalArgumentException("wrong method type");
final MethodHandle mh = target;
return samType.cast(Proxy.newProxyInstance(
samType.getClassLoader(),
new Class[]{ samType, MethodHandleProvider.class },
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getDeclaringClass() == MethodHandleProvider.class) {
return method.invoke(mh, args);
}
assert method.equals(sam) : method;
return mh.invokeVarargs(args);
}
}));
}
private static
Method getSamMethod(Class<?> samType) {
Method sam = null;
for (Method m : samType.getMethods()) {
int mod = m.getModifiers();
if (Modifier.isAbstract(mod)) {
if (sam != null)
return null; // too many abstract methods
sam = m;
}
}
if (!samType.isInterface() && getSamConstructor(samType) == null)
return null; // wrong kind of constructor
return sam;
}
private static
Constructor getSamConstructor(Class<?> samType) {
for (Constructor c : samType.getDeclaredConstructors()) {
if (c.getParameterTypes().length == 0) {
int mod = c.getModifiers();
if (Modifier.isPublic(mod) || Modifier.isProtected(mod))
return c;
}
}
return null;
}
} }
...@@ -40,24 +40,37 @@ import static sun.dyn.MemberName.newIllegalArgumentException; ...@@ -40,24 +40,37 @@ import static sun.dyn.MemberName.newIllegalArgumentException;
* returned by a method handle, or the arguments and return type passed * returned by a method handle, or the arguments and return type passed
* and expected by a method handle caller. Method types must be properly * and expected by a method handle caller. Method types must be properly
* matched between a method handle and all its callers, * matched between a method handle and all its callers,
* and the JVM's operations enforce this matching at all times. * and the JVM's operations enforce this matching at, specifically
* during calls to {@link MethodHandle#invokeExact}
* and {@link MethodHandle#invokeGeneric}, and during execution
* of {@code invokedynamic} instructions.
* <p> * <p>
* The structure is a return type accompanied by any number of parameter types. * The structure is a return type accompanied by any number of parameter types.
* The types (primitive, void, and reference) are represented by Class objects. * The types (primitive, {@code void}, and reference) are represented by {@link Class} objects.
* (For ease of exposition, we treat {@code void} as if it were a type.
* In fact, it denotes the absence of a return type.)
* <p> * <p>
* All instances of <code>MethodType</code> are immutable. * All instances of {@code MethodType} are immutable.
* Two instances are completely interchangeable if they compare equal. * Two instances are completely interchangeable if they compare equal.
* Equality depends on pairwise correspondence of the return and parameter types and on nothing else. * Equality depends on pairwise correspondence of the return and parameter types and on nothing else.
* <p> * <p>
* This type can be created only by factory methods. * This type can be created only by factory methods.
* All factory methods may cache values, though caching is not guaranteed. * All factory methods may cache values, though caching is not guaranteed.
* <p> * <p>
* Note: Like classes and strings, method types can be represented directly * {@code MethodType} objects are sometimes derived from bytecode instructions
* as constants to be loaded by {@code ldc} bytecodes. * such as {@code invokedynamic}, specifically from the type descriptor strings associated
* with the instructions in a class file's constant pool.
* When this occurs, any classes named in the descriptor strings must be loaded.
* (But they need not be initialized.)
* This loading may occur at any time before the {@code MethodType} object is first derived.
* <p>
* Like classes and strings, method types can be represented directly
* in a class file's constant pool as constants to be loaded by {@code ldc} bytecodes.
* Loading such a constant causes its component classes to be loaded as necessary.
* @author John Rose, JSR 292 EG * @author John Rose, JSR 292 EG
*/ */
public final public final
class MethodType { class MethodType implements java.lang.reflect.Type {
private final Class<?> rtype; private final Class<?> rtype;
private final Class<?>[] ptypes; private final Class<?>[] ptypes;
private MethodTypeForm form; // erased form, plus cached data about primitives private MethodTypeForm form; // erased form, plus cached data about primitives
...@@ -636,11 +649,11 @@ class MethodType { ...@@ -636,11 +649,11 @@ class MethodType {
/** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* Find or create an instance of the given method type. * Find or create an instance of the given method type.
* Any class or interface name embedded in the signature string * Any class or interface name embedded in the descriptor string
* will be resolved by calling {@link ClassLoader#loadClass(java.lang.String)} * will be resolved by calling {@link ClassLoader#loadClass(java.lang.String)}
* on the given loader (or if it is null, on the system class loader). * on the given loader (or if it is null, on the system class loader).
* <p> * <p>
* Note that it is possible to build method types which cannot be * Note that it is possible to encounter method types which cannot be
* constructed by this method, because their component types are * constructed by this method, because their component types are
* not all reachable from a common class loader. * not all reachable from a common class loader.
* <p> * <p>
...@@ -662,8 +675,11 @@ class MethodType { ...@@ -662,8 +675,11 @@ class MethodType {
} }
/** /**
* Create a bytecode signature representation of the type. * Create a bytecode descriptor representation of the method type.
* Note that this is not a strict inverse of * <p>
* Note that this is not a strict inverse of {@link #fromMethodDescriptorString}.
* Two distinct classes which share a common name but have different class loaders
* will appear identical when viewed within descriptor strings.
* <p> * <p>
* This method is included for the benfit of applications that must * This method is included for the benfit of applications that must
* generate bytecodes that process method handles and invokedynamic. * generate bytecodes that process method handles and invokedynamic.
......
...@@ -37,7 +37,7 @@ package java.dyn; ...@@ -37,7 +37,7 @@ package java.dyn;
* @author John Rose, JSR 292 EG * @author John Rose, JSR 292 EG
* @since 1.7 * @since 1.7
*/ */
public class NoAccessException extends RuntimeException { public class NoAccessException extends ReflectiveOperationException {
private static final long serialVersionUID = 292L; private static final long serialVersionUID = 292L;
/** /**
......
...@@ -40,20 +40,18 @@ ...@@ -40,20 +40,18 @@
* The JVM links any such call (regardless of signature) to a dynamically * The JVM links any such call (regardless of signature) to a dynamically
* typed method handle invocation. In the case of {@code invokeGeneric}, * typed method handle invocation. In the case of {@code invokeGeneric},
* argument and return value conversions are applied. * argument and return value conversions are applied.
* </li>
* *
* <li>In source code, the class {@link java.dyn.InvokeDynamic} appears to accept * <li>In source code, the class {@link java.dyn.InvokeDynamic InvokeDynamic} appears to accept
* any static method invocation, of any name and any signature. * any static method invocation, of any name and any signature.
* But instead of emitting * But instead of emitting
* an {@code invokestatic} instruction for such a call, the Java compiler emits * an {@code invokestatic} instruction for such a call, the Java compiler emits
* an {@code invokedynamic} instruction with the given name and signature. * an {@code invokedynamic} instruction with the given name and signature.
* * </li>
* <li>When the JVM links an {@code invokedynamic} instruction, it calls the
* {@linkplain java.dyn.Linkage#registerBootstrapMethod(Class, MethodHandle) bootstrap method}
* of the containing class to obtain a {@linkplain java.dyn.CallSite call site} object through which
* the call site will link its target {@linkplain java.dyn.MethodHandle method handle}.
* *
* <li>The JVM bytecode format supports immediate constants of * <li>The JVM bytecode format supports immediate constants of
* the classes {@link java.dyn.MethodHandle} and {@link java.dyn.MethodType}. * the classes {@link java.dyn.MethodHandle MethodHandle} and {@link java.dyn.MethodType MethodType}.
* </li>
* </ul> * </ul>
* *
* <h2><a name="jvm_mods"></a>Corresponding JVM bytecode format changes</h2> * <h2><a name="jvm_mods"></a>Corresponding JVM bytecode format changes</h2>
...@@ -65,18 +63,50 @@ ...@@ -65,18 +63,50 @@
* The first byte is the opcode 186 (hexadecimal {@code BA}). * 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 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 final two bytes are reserved for future use and required to be zero.
* The constant pool reference is to a entry with tag {@code CONSTANT_NameAndType} * The constant pool reference of an {@code invokedynamic} instruction is to a entry
* (decimal 12). It is thus not a method reference of any sort, but merely * with tag {@code CONSTANT_InvokeDynamic} (decimal 17). See below for its format.
* the method name, argument types, and return type of the dynamic call site. * The entry specifies the bootstrap method (a {@link java.dyn.MethodHandle MethodHandle} constant),
* <em>(TBD: The EG is discussing the possibility of a special constant pool entry type, * the dynamic invocation name, and the argument types and return type of the call.
* so that other information may be added, such as a per-instruction bootstrap * <p>
* method and/or annotations.)</em> * 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>
* Moreover, for the purpose of distinguishing dynamic call sites,
* the JVM is allowed (but not required) to make internal copies
* of {@code invokedynamic} instructions, each one
* constituting a separate dynamic call site with its own linkage state.
* Such copying, if it occurs, cannot be observed except indirectly via
* execution of bootstrap methods and target methods.
* <p>
* A dynamic call site is originally in an unlinked state. In this state, there is
* 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>.
* <p>
* <em>(Historic Note: Some older JVMs may allow the index of a {@code CONSTANT_NameAndType}
* instead of a {@code CONSTANT_InvokeDynamic}. In earlier, obsolete versions of this API, the
* bootstrap method was specified dynamically, in a per-class basis, during class initialization.)</em>
*
* <h3>constant pool entries for {@code invokedynamic} instructions</h3>
* If a constant pool entry has the tag {@code CONSTANT_InvokeDynamic} (decimal 17),
* it must contain exactly four more bytes.
* The first two bytes after the tag must be an index to a {@code CONSTANT_MethodHandle}
* entry, and the second two bytes must be an index to a {@code CONSTANT_NameAndType}.
* 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 {@code CONSTANT_Class} reference in a {@code CONSTANT_Methodref} entry
* is replaced by a bootstrap method reference.
* *
* <h3>constant pool entries for {@code MethodType}s</h3> * <h3>constant pool entries for {@code MethodType}s</h3>
* If a constant pool entry has the tag {@code CONSTANT_MethodType} (decimal 16), * If a constant pool entry has the tag {@code CONSTANT_MethodType} (decimal 16),
* it must contain exactly two more bytes, which are an index to a {@code CONSTANT_Utf8} * it must contain exactly two more bytes, which must be an index to a {@code CONSTANT_Utf8}
* entry which represents a method type signature. The JVM will ensure that on first * entry which represents a method type signature.
* execution of an {@code ldc} instruction for this entry, a {@link java.dyn.MethodType} * <p>
* The JVM will ensure that on first
* execution of an {@code ldc} instruction for this entry, a {@link java.dyn.MethodType MethodType}
* will be created which represents the signature. * will be created which represents the signature.
* Any classes mentioned in the {@code MethodType} will be loaded if necessary, * Any classes mentioned in the {@code MethodType} will be loaded if necessary,
* but not initialized. * but not initialized.
...@@ -86,12 +116,15 @@ ...@@ -86,12 +116,15 @@
* <h3>constant pool entries for {@code MethodHandle}s</h3> * <h3>constant pool entries for {@code MethodHandle}s</h3>
* If a constant pool entry has the tag {@code CONSTANT_MethodHandle} (decimal 15), * 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 * it must contain exactly three more bytes. The first byte after the tag is a subtag
* value in the range 1 through 9, and the last two are an index to a * 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_Fieldref}, {@code CONSTANT_Methodref}, or
* {@code CONSTANT_InterfaceMethodref} entry which represents a field or method * {@code CONSTANT_InterfaceMethodref} entry which represents a field or method
* for which a method handle is to be created. * 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 * The JVM will ensure that on first execution of an {@code ldc} instruction
* for this entry, a {@link java.dyn.MethodHandle} will be created which represents * for this entry, a {@link java.dyn.MethodHandle MethodHandle} will be created which represents
* the field or method reference, according to the specific mode implied by the subtag. * the field or method reference, according to the specific mode implied by the subtag.
* <p> * <p>
* As with {@code CONSTANT_Class} and {@code CONSTANT_MethodType} constants, * As with {@code CONSTANT_Class} and {@code CONSTANT_MethodType} constants,
...@@ -126,6 +159,129 @@ ...@@ -126,6 +159,129 @@
* Method handles for subtags {@code REF_getStatic}, {@code REF_putStatic}, and {@code REF_invokeStatic} * Method handles 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. * may force class initialization on their first invocation, just like the corresponding bytecodes.
* *
* <h2><a name="bsm"></a>Bootstrap Methods</h2>
* Before the JVM can execute a dynamic call site (an {@code invokedynamic} instruction),
* the call site must first be <em>linked</em>.
* Linking is accomplished by calling a <em>bootstrap method</em>
* which is given the static information content of the call site,
* and which must produce a {@link java.dyn.MethodHandle method handle}
* that gives the behavior of the call site.
* <p>
* Each {@code invokedynamic} instruction statically specifies its own
* bootstrap method as a constant pool reference.
* The constant pool reference also specifies the call site's name and type signature,
* just like {@code invokevirtual} and the other invoke instructions.
* <p>
* Linking starts with resolving the constant pool entry for the
* bootstrap method, and resolving a {@link java.dyn.MethodType MethodType} object for
* the type signature of the dynamic call site.
* This resolution process may trigger class loading.
* It may therefore throw an error if a class fails to load.
* This error becomes the abnormal termination of the dynamic
* call site execution.
* Linkage does not trigger class initialization.
* <p>
* Next, the bootstrap method call is started, with four values being stacked:
* <ul>
* <li>a {@code MethodHandle}, the resolved bootstrap method itself </li>
* <li>a {@code Class}, 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 MethodType}, the resolved type signature of the call </li>
* </ul>
* The method handle is then applied to the other values as if by
* {@linkplain java.dyn.MethodHandle#invokeGeneric the <code>invokeGeneric</code> method}.
* The returned result must be a {@link java.dyn.CallSite CallSite}, a {@link java.dyn.MethodHandle MethodHandle},
* or another {@link java.dyn.MethodHandleProvider MethodHandleProvider} value.
* The method {@linkplain java.dyn.MethodHandleProvider#asMethodHandle asMethodHandle}
* is then called on the returned value. The result of that second
* call is the {@code MethodHandle} which becomes the
* permanent binding for the dynamic call site.
* That method handle's type must be exactly equal to the type
* derived from the dynamic call site signature and passed to
* the bootstrap method.
* <p>
* After resolution, the linkage process may fail in a variety of ways.
* All failures are reported by an {@link java.dyn.InvokeDynamicBootstrapError InvokeDynamicBootstrapError},
* which is thrown as the abnormal termination of the dynamic call
* site execution.
* The following circumstances will cause this:
* <ul>
* <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.dyn.MethodHandleProvider MethodHandleProvider} </li>
* <li>the call to {@code asMethodHandle} completes abnormally </li>
* <li>the call to {@code asMethodHandle} fails to return a reference to
* an object of type {@link java.dyn.MethodHandle MethodHandle} </li>
* <li>the method handle produced by {@code asMethodHandle} does not have
* the expected {@code MethodType} </li>
* </ul>
* <h3>timing of linkage</h3>
* A dynamic call site is linked just before its first execution.
* The bootstrap method call implementing the linkage occurs within
* a thread that is attempting a first execution.
* <p>
* If there are several such threads, the JVM picks one thread
* and runs the bootstrap method while the others wait for the
* invocation to terminate normally or abnormally.
* <p>
* After a bootstrap method is called and a method handle target
* successfully extracted, the JVM attempts to link the instruction
* being executed to the target method handle.
* This may fail if there has been intervening linkage
* or invalidation event for the same instruction.
* If such a failure occurs, the dynamic call site must be
* re-executed from the beginning, either re-linking it
* (if it has been invalidated) or invoking the target
* (if it the instruction has been linked by some other means).
* <p>
* If the instruction is linked successfully, the target method
* handle is invoked to complete the instruction execution.
* The state of linkage continues until the method containing the
* dynamic call site is garbage collected, or the dynamic call site
* is invalidated by an explicit request,
* such as {@link java.dyn.Linkage#invalidateCallerClass Linkage.invalidateCallerClass}.
* <p>
* In an application which requires dynamic call sites with individually
* mutable behaviors, their bootstrap methods should produce distinct
* {@link java.dyn.CallSite CallSite} objects, one for each linkage request.
* <p>
* If a class containing {@code invokedynamic} instructions
* is {@linkplain java.dyn.Linkage#invalidateCallerClass(Class) invalidated},
* subsequent execution of those {@code invokedynamic} instructions
* will require linking.
* It is as if they had never been executed in the first place.
* (However, invalidation does not cause constant pool entries to be
* resolved a second time.)
* <p>
* Invalidation events and bootstrap method calls for a particular
* dynamic call site are globally ordered relative to each other.
* When an invokedynamic instruction is invalidated, if there is
* simultaneously a bootstrap method invocation in process
* (in the same thread or a different thread), the result
* eventually returned must not be used to link the call site.
* Put another way, when a call site is invalidated, its
* subsequent linkage (if any) must be performed by a bootstrap method
* call initiated after the invalidation occurred.
* <p>
* If several threads simultaneously execute a bootstrap method for a single dynamic
* call site, the JVM must choose one target object and installs it visibly to
* 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
* chosen target object.
* <p>
* The JVM is free to duplicate dynamic call sites.
* This means that, even if a class contains just one {@code invokedynamic}
* instruction, its bootstrap method may be executed several times,
* once for each duplicate. Thus, bootstrap method code should not
* assume an exclusive one-to-one correspondence between particular occurrences
* of {@code invokedynamic} bytecodes in class files and linkage events.
* <p>
* In principle, each individual execution of an {@code invokedynamic}
* instruction could be deemed (by a conforming implementation) to be a separate
* duplicate, requiring its own execution of the bootstrap method.
* However, implementations are expected to perform code duplication
* (if at all) in order to improve performance, not make it worse.
*
* @author John Rose, JSR 292 EG * @author John Rose, JSR 292 EG
*/ */
......
/* /*
* Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 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
...@@ -265,7 +265,7 @@ public class ObjectInputStream ...@@ -265,7 +265,7 @@ public class ObjectInputStream
* object currently being deserialized and descriptor for current class. * object currently being deserialized and descriptor for current class.
* Null when not during readObject upcall. * Null when not during readObject upcall.
*/ */
private CallbackContext curContext; private SerialCallbackContext curContext;
/** /**
* Creates an ObjectInputStream that reads from the specified InputStream. * Creates an ObjectInputStream that reads from the specified InputStream.
...@@ -1798,7 +1798,7 @@ public class ObjectInputStream ...@@ -1798,7 +1798,7 @@ public class ObjectInputStream
private void readExternalData(Externalizable obj, ObjectStreamClass desc) private void readExternalData(Externalizable obj, ObjectStreamClass desc)
throws IOException throws IOException
{ {
CallbackContext oldContext = curContext; SerialCallbackContext oldContext = curContext;
curContext = null; curContext = null;
try { try {
boolean blocked = desc.hasBlockExternalData(); boolean blocked = desc.hasBlockExternalData();
...@@ -1857,10 +1857,10 @@ public class ObjectInputStream ...@@ -1857,10 +1857,10 @@ public class ObjectInputStream
slotDesc.hasReadObjectMethod() && slotDesc.hasReadObjectMethod() &&
handles.lookupException(passHandle) == null) handles.lookupException(passHandle) == null)
{ {
CallbackContext oldContext = curContext; SerialCallbackContext oldContext = curContext;
try { try {
curContext = new CallbackContext(obj, slotDesc); curContext = new SerialCallbackContext(obj, slotDesc);
bin.setBlockDataMode(true); bin.setBlockDataMode(true);
slotDesc.invokeReadObject(obj, this); slotDesc.invokeReadObject(obj, this);
...@@ -3505,42 +3505,4 @@ public class ObjectInputStream ...@@ -3505,42 +3505,4 @@ public class ObjectInputStream
} }
} }
/**
* Context that during upcalls to class-defined readObject methods; holds
* object currently being deserialized and descriptor for current class.
* This context keeps a boolean state to indicate that defaultReadObject
* or readFields has already been invoked with this context or the class's
* readObject method has returned; if true, the getObj method throws
* NotActiveException.
*/
private static class CallbackContext {
private final Object obj;
private final ObjectStreamClass desc;
private final AtomicBoolean used = new AtomicBoolean();
public CallbackContext(Object obj, ObjectStreamClass desc) {
this.obj = obj;
this.desc = desc;
}
public Object getObj() throws NotActiveException {
checkAndSetUsed();
return obj;
}
public ObjectStreamClass getDesc() {
return desc;
}
private void checkAndSetUsed() throws NotActiveException {
if (!used.compareAndSet(false, true)) {
throw new NotActiveException(
"not in readObject invocation or fields already read");
}
}
public void setUsed() {
used.set(true);
}
}
} }
/* /*
* Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 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
...@@ -35,6 +35,7 @@ import java.util.List; ...@@ -35,6 +35,7 @@ import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import static java.io.ObjectStreamClass.processQueue; import static java.io.ObjectStreamClass.processQueue;
import java.io.SerialCallbackContext;
/** /**
* An ObjectOutputStream writes primitive data types and graphs of Java objects * An ObjectOutputStream writes primitive data types and graphs of Java objects
...@@ -191,10 +192,12 @@ public class ObjectOutputStream ...@@ -191,10 +192,12 @@ public class ObjectOutputStream
private boolean enableReplace; private boolean enableReplace;
// values below valid only during upcalls to writeObject()/writeExternal() // values below valid only during upcalls to writeObject()/writeExternal()
/** object currently being serialized */ /**
private Object curObj; * Context during upcalls to class-defined writeObject methods; holds
/** descriptor for current class (null if in writeExternal()) */ * object currently being serialized and descriptor for current class.
private ObjectStreamClass curDesc; * Null when not during writeObject upcall.
*/
private SerialCallbackContext curContext;
/** current PutField object */ /** current PutField object */
private PutFieldImpl curPut; private PutFieldImpl curPut;
...@@ -426,9 +429,11 @@ public class ObjectOutputStream ...@@ -426,9 +429,11 @@ public class ObjectOutputStream
* <code>OutputStream</code> * <code>OutputStream</code>
*/ */
public void defaultWriteObject() throws IOException { public void defaultWriteObject() throws IOException {
if (curObj == null || curDesc == null) { if ( curContext == null ) {
throw new NotActiveException("not in call to writeObject"); throw new NotActiveException("not in call to writeObject");
} }
Object curObj = curContext.getObj();
ObjectStreamClass curDesc = curContext.getDesc();
bout.setBlockDataMode(false); bout.setBlockDataMode(false);
defaultWriteFields(curObj, curDesc); defaultWriteFields(curObj, curDesc);
bout.setBlockDataMode(true); bout.setBlockDataMode(true);
...@@ -446,9 +451,11 @@ public class ObjectOutputStream ...@@ -446,9 +451,11 @@ public class ObjectOutputStream
*/ */
public ObjectOutputStream.PutField putFields() throws IOException { public ObjectOutputStream.PutField putFields() throws IOException {
if (curPut == null) { if (curPut == null) {
if (curObj == null || curDesc == null) { if (curContext == null) {
throw new NotActiveException("not in call to writeObject"); throw new NotActiveException("not in call to writeObject");
} }
Object curObj = curContext.getObj();
ObjectStreamClass curDesc = curContext.getDesc();
curPut = new PutFieldImpl(curDesc); curPut = new PutFieldImpl(curDesc);
} }
return curPut; return curPut;
...@@ -1420,17 +1427,15 @@ public class ObjectOutputStream ...@@ -1420,17 +1427,15 @@ public class ObjectOutputStream
* writeExternal() method. * writeExternal() method.
*/ */
private void writeExternalData(Externalizable obj) throws IOException { private void writeExternalData(Externalizable obj) throws IOException {
Object oldObj = curObj;
ObjectStreamClass oldDesc = curDesc;
PutFieldImpl oldPut = curPut; PutFieldImpl oldPut = curPut;
curObj = obj;
curDesc = null;
curPut = null; curPut = null;
if (extendedDebugInfo) { if (extendedDebugInfo) {
debugInfoStack.push("writeExternal data"); debugInfoStack.push("writeExternal data");
} }
SerialCallbackContext oldContext = curContext;
try { try {
curContext = null;
if (protocol == PROTOCOL_VERSION_1) { if (protocol == PROTOCOL_VERSION_1) {
obj.writeExternal(this); obj.writeExternal(this);
} else { } else {
...@@ -1440,13 +1445,12 @@ public class ObjectOutputStream ...@@ -1440,13 +1445,12 @@ public class ObjectOutputStream
bout.writeByte(TC_ENDBLOCKDATA); bout.writeByte(TC_ENDBLOCKDATA);
} }
} finally { } finally {
curContext = oldContext;
if (extendedDebugInfo) { if (extendedDebugInfo) {
debugInfoStack.pop(); debugInfoStack.pop();
} }
} }
curObj = oldObj;
curDesc = oldDesc;
curPut = oldPut; curPut = oldPut;
} }
...@@ -1461,12 +1465,9 @@ public class ObjectOutputStream ...@@ -1461,12 +1465,9 @@ public class ObjectOutputStream
for (int i = 0; i < slots.length; i++) { for (int i = 0; i < slots.length; i++) {
ObjectStreamClass slotDesc = slots[i].desc; ObjectStreamClass slotDesc = slots[i].desc;
if (slotDesc.hasWriteObjectMethod()) { if (slotDesc.hasWriteObjectMethod()) {
Object oldObj = curObj;
ObjectStreamClass oldDesc = curDesc;
PutFieldImpl oldPut = curPut; PutFieldImpl oldPut = curPut;
curObj = obj;
curDesc = slotDesc;
curPut = null; curPut = null;
SerialCallbackContext oldContext = curContext;
if (extendedDebugInfo) { if (extendedDebugInfo) {
debugInfoStack.push( debugInfoStack.push(
...@@ -1474,18 +1475,19 @@ public class ObjectOutputStream ...@@ -1474,18 +1475,19 @@ public class ObjectOutputStream
slotDesc.getName() + "\")"); slotDesc.getName() + "\")");
} }
try { try {
curContext = new SerialCallbackContext(obj, slotDesc);
bout.setBlockDataMode(true); bout.setBlockDataMode(true);
slotDesc.invokeWriteObject(obj, this); slotDesc.invokeWriteObject(obj, this);
bout.setBlockDataMode(false); bout.setBlockDataMode(false);
bout.writeByte(TC_ENDBLOCKDATA); bout.writeByte(TC_ENDBLOCKDATA);
} finally { } finally {
curContext.setUsed();
curContext = oldContext;
if (extendedDebugInfo) { if (extendedDebugInfo) {
debugInfoStack.pop(); debugInfoStack.pop();
} }
} }
curObj = oldObj;
curDesc = oldDesc;
curPut = oldPut; curPut = oldPut;
} else { } else {
defaultWriteFields(obj, slotDesc); defaultWriteFields(obj, slotDesc);
......
/* /*
* Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 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
...@@ -1830,8 +1830,10 @@ public class ObjectStreamClass implements Serializable { ...@@ -1830,8 +1830,10 @@ public class ObjectStreamClass implements Serializable {
private final ObjectStreamField[] fields; private final ObjectStreamField[] fields;
/** number of primitive fields */ /** number of primitive fields */
private final int numPrimFields; private final int numPrimFields;
/** unsafe field keys */ /** unsafe field keys for reading fields - may contain dupes */
private final long[] keys; private final long[] readKeys;
/** unsafe fields keys for writing fields - no dupes */
private final long[] writeKeys;
/** field data offsets */ /** field data offsets */
private final int[] offsets; private final int[] offsets;
/** field type codes */ /** field type codes */
...@@ -1849,16 +1851,22 @@ public class ObjectStreamClass implements Serializable { ...@@ -1849,16 +1851,22 @@ public class ObjectStreamClass implements Serializable {
FieldReflector(ObjectStreamField[] fields) { FieldReflector(ObjectStreamField[] fields) {
this.fields = fields; this.fields = fields;
int nfields = fields.length; int nfields = fields.length;
keys = new long[nfields]; readKeys = new long[nfields];
writeKeys = new long[nfields];
offsets = new int[nfields]; offsets = new int[nfields];
typeCodes = new char[nfields]; typeCodes = new char[nfields];
ArrayList<Class<?>> typeList = new ArrayList<Class<?>>(); ArrayList<Class<?>> typeList = new ArrayList<Class<?>>();
Set<Long> usedKeys = new HashSet<Long>();
for (int i = 0; i < nfields; i++) { for (int i = 0; i < nfields; i++) {
ObjectStreamField f = fields[i]; ObjectStreamField f = fields[i];
Field rf = f.getField(); Field rf = f.getField();
keys[i] = (rf != null) ? long key = (rf != null) ?
unsafe.objectFieldOffset(rf) : Unsafe.INVALID_FIELD_OFFSET; unsafe.objectFieldOffset(rf) : Unsafe.INVALID_FIELD_OFFSET;
readKeys[i] = key;
writeKeys[i] = usedKeys.add(key) ?
key : Unsafe.INVALID_FIELD_OFFSET;
offsets[i] = f.getOffset(); offsets[i] = f.getOffset();
typeCodes[i] = f.getTypeCode(); typeCodes[i] = f.getTypeCode();
if (!f.isPrimitive()) { if (!f.isPrimitive()) {
...@@ -1894,7 +1902,7 @@ public class ObjectStreamClass implements Serializable { ...@@ -1894,7 +1902,7 @@ public class ObjectStreamClass implements Serializable {
* in array should be equal to Unsafe.INVALID_FIELD_OFFSET. * in array should be equal to Unsafe.INVALID_FIELD_OFFSET.
*/ */
for (int i = 0; i < numPrimFields; i++) { for (int i = 0; i < numPrimFields; i++) {
long key = keys[i]; long key = readKeys[i];
int off = offsets[i]; int off = offsets[i];
switch (typeCodes[i]) { switch (typeCodes[i]) {
case 'Z': case 'Z':
...@@ -1945,7 +1953,7 @@ public class ObjectStreamClass implements Serializable { ...@@ -1945,7 +1953,7 @@ public class ObjectStreamClass implements Serializable {
throw new NullPointerException(); throw new NullPointerException();
} }
for (int i = 0; i < numPrimFields; i++) { for (int i = 0; i < numPrimFields; i++) {
long key = keys[i]; long key = writeKeys[i];
if (key == Unsafe.INVALID_FIELD_OFFSET) { if (key == Unsafe.INVALID_FIELD_OFFSET) {
continue; // discard value continue; // discard value
} }
...@@ -2006,7 +2014,7 @@ public class ObjectStreamClass implements Serializable { ...@@ -2006,7 +2014,7 @@ public class ObjectStreamClass implements Serializable {
switch (typeCodes[i]) { switch (typeCodes[i]) {
case 'L': case 'L':
case '[': case '[':
vals[offsets[i]] = unsafe.getObject(obj, keys[i]); vals[offsets[i]] = unsafe.getObject(obj, readKeys[i]);
break; break;
default: default:
...@@ -2027,7 +2035,7 @@ public class ObjectStreamClass implements Serializable { ...@@ -2027,7 +2035,7 @@ public class ObjectStreamClass implements Serializable {
throw new NullPointerException(); throw new NullPointerException();
} }
for (int i = numPrimFields; i < fields.length; i++) { for (int i = numPrimFields; i < fields.length; i++) {
long key = keys[i]; long key = writeKeys[i];
if (key == Unsafe.INVALID_FIELD_OFFSET) { if (key == Unsafe.INVALID_FIELD_OFFSET) {
continue; // discard value continue; // discard value
} }
......
/*
* %W% %E%
*
* Copyright (c) 2006, 2010 Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package java.io;
/**
* Context during upcalls from object stream to class-defined
* readObject/writeObject methods.
* Holds object currently being deserialized and descriptor for current class.
*
* This context keeps track of the thread it was constructed on, and allows
* only a single call of defaultReadObject, readFields, defaultWriteObject
* or writeFields which must be invoked on the same thread before the class's
* readObject/writeObject method has returned.
* If not set to the current thread, the getObj method throws NotActiveException.
*/
final class SerialCallbackContext {
private final Object obj;
private final ObjectStreamClass desc;
/**
* Thread this context is in use by.
* As this only works in one thread, we do not need to worry about thread-safety.
*/
private Thread thread;
public SerialCallbackContext(Object obj, ObjectStreamClass desc) {
this.obj = obj;
this.desc = desc;
this.thread = Thread.currentThread();
}
public Object getObj() throws NotActiveException {
checkAndSetUsed();
return obj;
}
public ObjectStreamClass getDesc() {
return desc;
}
private void checkAndSetUsed() throws NotActiveException {
if (thread != Thread.currentThread()) {
throw new NotActiveException(
"not in readObject invocation or fields already read");
}
thread = null;
}
public void setUsed() {
thread = null;
}
}
...@@ -100,7 +100,8 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { ...@@ -100,7 +100,8 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* @param minimumCapacity the minimum desired capacity. * @param minimumCapacity the minimum desired capacity.
*/ */
public void ensureCapacity(int minimumCapacity) { public void ensureCapacity(int minimumCapacity) {
ensureCapacityInternal(minimumCapacity); if (minimumCapacity > 0)
ensureCapacityInternal(minimumCapacity);
} }
/** /**
...@@ -108,6 +109,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { ...@@ -108,6 +109,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* never synchronized. * never synchronized.
*/ */
private void ensureCapacityInternal(int minimumCapacity) { private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0) if (minimumCapacity - value.length > 0)
expandCapacity(minimumCapacity); expandCapacity(minimumCapacity);
} }
......
...@@ -553,6 +553,13 @@ public abstract class ClassLoader { ...@@ -553,6 +553,13 @@ public abstract class ClassLoader {
* If either <tt>off</tt> or <tt>len</tt> is negative, or if * If either <tt>off</tt> or <tt>len</tt> is negative, or if
* <tt>off+len</tt> is greater than <tt>b.length</tt>. * <tt>off+len</tt> is greater than <tt>b.length</tt>.
* *
* @throws SecurityException
* If an attempt is made to add this class to a package that
* contains classes that were signed by a different set of
* certificates than this class, or if an attempt is made
* to define a class in a package with a fully-qualified name
* that starts with "{@code java.}".
*
* @see #loadClass(String, boolean) * @see #loadClass(String, boolean)
* @see #resolveClass(Class) * @see #resolveClass(Class)
* *
......
...@@ -28,9 +28,7 @@ package java.net; ...@@ -28,9 +28,7 @@ package java.net;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.InterruptedIOException;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import java.io.ByteArrayOutputStream;
import sun.net.ConnectionResetException; import sun.net.ConnectionResetException;
import sun.net.NetHooks; import sun.net.NetHooks;
...@@ -58,7 +56,7 @@ abstract class AbstractPlainSocketImpl extends SocketImpl ...@@ -58,7 +56,7 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
protected int fdUseCount = 0; protected int fdUseCount = 0;
/* lock when increment/decrementing fdUseCount */ /* lock when increment/decrementing fdUseCount */
protected Object fdLock = new Object(); protected final Object fdLock = new Object();
/* indicates a close is pending on the file descriptor */ /* indicates a close is pending on the file descriptor */
protected boolean closePending = false; protected boolean closePending = false;
...@@ -68,7 +66,7 @@ abstract class AbstractPlainSocketImpl extends SocketImpl ...@@ -68,7 +66,7 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
private int CONNECTION_RESET_PENDING = 1; private int CONNECTION_RESET_PENDING = 1;
private int CONNECTION_RESET = 2; private int CONNECTION_RESET = 2;
private int resetState; private int resetState;
private Object resetLock = new Object(); private final Object resetLock = new Object();
/** /**
* Load net library into runtime. * Load net library into runtime.
...@@ -100,25 +98,24 @@ abstract class AbstractPlainSocketImpl extends SocketImpl ...@@ -100,25 +98,24 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
protected void connect(String host, int port) protected void connect(String host, int port)
throws UnknownHostException, IOException throws UnknownHostException, IOException
{ {
IOException pending = null; boolean connected = false;
try { try {
InetAddress address = InetAddress.getByName(host); InetAddress address = InetAddress.getByName(host);
this.port = port; this.port = port;
this.address = address; this.address = address;
try { connectToAddress(address, port, timeout);
connectToAddress(address, port, timeout); connected = true;
return; } finally {
} catch (IOException e) { if (!connected) {
pending = e; try {
close();
} catch (IOException ioe) {
/* Do nothing. If connect threw an exception then
it will be passed up the call stack */
}
} }
} catch (UnknownHostException e) {
pending = e;
} }
// everything failed
close();
throw pending;
} }
/** /**
...@@ -151,22 +148,29 @@ abstract class AbstractPlainSocketImpl extends SocketImpl ...@@ -151,22 +148,29 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
* SocketAddress subclass not supported by this socket * SocketAddress subclass not supported by this socket
* @since 1.4 * @since 1.4
*/ */
protected void connect(SocketAddress address, int timeout) throws IOException { protected void connect(SocketAddress address, int timeout)
if (address == null || !(address instanceof InetSocketAddress)) throws IOException {
throw new IllegalArgumentException("unsupported address type"); boolean connected = false;
InetSocketAddress addr = (InetSocketAddress) address;
if (addr.isUnresolved())
throw new UnknownHostException(addr.getHostName());
this.port = addr.getPort();
this.address = addr.getAddress();
try { try {
if (address == null || !(address instanceof InetSocketAddress))
throw new IllegalArgumentException("unsupported address type");
InetSocketAddress addr = (InetSocketAddress) address;
if (addr.isUnresolved())
throw new UnknownHostException(addr.getHostName());
this.port = addr.getPort();
this.address = addr.getAddress();
connectToAddress(this.address, port, timeout); connectToAddress(this.address, port, timeout);
return; connected = true;
} catch (IOException e) { } finally {
// everything failed if (!connected) {
close(); try {
throw e; close();
} catch (IOException ioe) {
/* Do nothing. If connect threw an exception then
it will be passed up the call stack */
}
}
} }
} }
...@@ -311,7 +315,7 @@ abstract class AbstractPlainSocketImpl extends SocketImpl ...@@ -311,7 +315,7 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
} }
} }
try { try {
FileDescriptor fd = acquireFD(); acquireFD();
try { try {
socketConnect(address, port, timeout); socketConnect(address, port, timeout);
/* socket may have been closed during poll/select */ /* socket may have been closed during poll/select */
...@@ -370,7 +374,7 @@ abstract class AbstractPlainSocketImpl extends SocketImpl ...@@ -370,7 +374,7 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
* @param s the connection * @param s the connection
*/ */
protected void accept(SocketImpl s) throws IOException { protected void accept(SocketImpl s) throws IOException {
FileDescriptor fd = acquireFD(); acquireFD();
try { try {
socketAccept(s); socketAccept(s);
} finally { } finally {
...@@ -562,7 +566,6 @@ abstract class AbstractPlainSocketImpl extends SocketImpl ...@@ -562,7 +566,6 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
close(); close();
} }
/* /*
* "Acquires" and returns the FileDescriptor for this impl * "Acquires" and returns the FileDescriptor for this impl
* *
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
package java.nio; package java.nio;
import java.io.FileDescriptor;
import sun.misc.Cleaner; import sun.misc.Cleaner;
import sun.misc.Unsafe; import sun.misc.Unsafe;
import sun.misc.VM; import sun.misc.VM;
...@@ -114,7 +115,7 @@ class Direct$Type$Buffer$RW$$BO$ ...@@ -114,7 +115,7 @@ class Direct$Type$Buffer$RW$$BO$
// //
Direct$Type$Buffer$RW$(int cap) { // package-private Direct$Type$Buffer$RW$(int cap) { // package-private
#if[rw] #if[rw]
super(-1, 0, cap, cap, false); super(-1, 0, cap, cap);
boolean pa = VM.isDirectMemoryPageAligned(); boolean pa = VM.isDirectMemoryPageAligned();
int ps = Bits.pageSize(); int ps = Bits.pageSize();
long size = Math.max(1L, (long)cap + (pa ? ps : 0)); long size = Math.max(1L, (long)cap + (pa ? ps : 0));
...@@ -145,7 +146,7 @@ class Direct$Type$Buffer$RW$$BO$ ...@@ -145,7 +146,7 @@ class Direct$Type$Buffer$RW$$BO$
// Invoked only by JNI: NewDirectByteBuffer(void*, long) // Invoked only by JNI: NewDirectByteBuffer(void*, long)
// //
private Direct$Type$Buffer(long addr, int cap) { private Direct$Type$Buffer(long addr, int cap) {
super(-1, 0, cap, cap, false); super(-1, 0, cap, cap);
address = addr; address = addr;
cleaner = null; cleaner = null;
} }
...@@ -154,14 +155,17 @@ class Direct$Type$Buffer$RW$$BO$ ...@@ -154,14 +155,17 @@ class Direct$Type$Buffer$RW$$BO$
// For memory-mapped buffers -- invoked by FileChannelImpl via reflection // For memory-mapped buffers -- invoked by FileChannelImpl via reflection
// //
protected Direct$Type$Buffer$RW$(int cap, long addr, Runnable unmapper) { protected Direct$Type$Buffer$RW$(int cap, long addr,
FileDescriptor fd,
Runnable unmapper)
{
#if[rw] #if[rw]
super(-1, 0, cap, cap, true); super(-1, 0, cap, cap, fd);
address = addr; address = addr;
viewedBuffer = null; viewedBuffer = null;
cleaner = Cleaner.create(this, unmapper); cleaner = Cleaner.create(this, unmapper);
#else[rw] #else[rw]
super(cap, addr, unmapper); super(cap, addr, fd, unmapper);
#end[rw] #end[rw]
} }
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
package java.nio; package java.nio;
import java.io.FileDescriptor;
import sun.misc.Unsafe; import sun.misc.Unsafe;
...@@ -71,26 +72,26 @@ public abstract class MappedByteBuffer ...@@ -71,26 +72,26 @@ public abstract class MappedByteBuffer
// for optimization purposes, it's easier to do it the other way around. // for optimization purposes, it's easier to do it the other way around.
// This works because DirectByteBuffer is a package-private class. // This works because DirectByteBuffer is a package-private class.
// Volatile to make sure that the finalization thread sees the current // For mapped buffers, a FileDescriptor that may be used for mapping
// value of this so that a region is not accidentally unmapped again later. // operations if valid; null if the buffer is not mapped.
volatile boolean isAMappedBuffer; // package-private private final FileDescriptor fd;
// This should only be invoked by the DirectByteBuffer constructors // This should only be invoked by the DirectByteBuffer constructors
// //
MappedByteBuffer(int mark, int pos, int lim, int cap, // package-private MappedByteBuffer(int mark, int pos, int lim, int cap, // package-private
boolean mapped) FileDescriptor fd)
{ {
super(mark, pos, lim, cap); super(mark, pos, lim, cap);
isAMappedBuffer = mapped; this.fd = fd;
} }
MappedByteBuffer(int mark, int pos, int lim, int cap) { // package-private MappedByteBuffer(int mark, int pos, int lim, int cap) { // package-private
super(mark, pos, lim, cap); super(mark, pos, lim, cap);
isAMappedBuffer = false; this.fd = null;
} }
private void checkMapped() { private void checkMapped() {
if (!isAMappedBuffer) if (fd == null)
// Can only happen if a luser explicitly casts a direct byte buffer // Can only happen if a luser explicitly casts a direct byte buffer
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
...@@ -191,13 +192,12 @@ public abstract class MappedByteBuffer ...@@ -191,13 +192,12 @@ public abstract class MappedByteBuffer
checkMapped(); checkMapped();
if ((address != 0) && (capacity() != 0)) { if ((address != 0) && (capacity() != 0)) {
long offset = mappingOffset(); long offset = mappingOffset();
force0(mappingAddress(offset), mappingLength(offset)); force0(fd, mappingAddress(offset), mappingLength(offset));
} }
return this; return this;
} }
private native boolean isLoaded0(long address, long length, int pageCount); private native boolean isLoaded0(long address, long length, int pageCount);
private native void load0(long address, long length); private native void load0(long address, long length);
private native void force0(long address, long length); private native void force0(FileDescriptor fd, long address, long length);
} }
...@@ -232,8 +232,6 @@ ...@@ -232,8 +232,6 @@
* <td>An asynchronous channel to a stream-oriented connecting socket</td></tr> * <td>An asynchronous channel to a stream-oriented connecting socket</td></tr>
* <tr><td valign=top><tt>{@link java.nio.channels.AsynchronousServerSocketChannel}&nbsp;&nbsp;</tt></td> * <tr><td valign=top><tt>{@link java.nio.channels.AsynchronousServerSocketChannel}&nbsp;&nbsp;</tt></td>
* <td>An asynchronous channel to a stream-oriented listening socket</td></tr> * <td>An asynchronous channel to a stream-oriented listening socket</td></tr>
* <tr><td valign=top><tt>{@link java.nio.channels.AsynchronousDatagramChannel}</tt></td>
* <td>An asynchronous channel to a datagram-oriented socket</td></tr>
* <tr><td valign=top><tt>{@link java.nio.channels.CompletionHandler}</tt></td> * <tr><td valign=top><tt>{@link java.nio.channels.CompletionHandler}</tt></td>
* <td>A handler for consuming the result of an asynchronous operation</td></tr> * <td>A handler for consuming the result of an asynchronous operation</td></tr>
* <tr><td valign=top><tt>{@link java.nio.channels.AsynchronousChannelGroup}</tt></td> * <tr><td valign=top><tt>{@link java.nio.channels.AsynchronousChannelGroup}</tt></td>
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
package java.nio.channels.spi; package java.nio.channels.spi;
import java.nio.channels.*; import java.nio.channels.*;
import java.net.ProtocolFamily;
import java.io.IOException; import java.io.IOException;
import java.util.Iterator; import java.util.Iterator;
import java.util.ServiceLoader; import java.util.ServiceLoader;
...@@ -239,26 +238,4 @@ public abstract class AsynchronousChannelProvider { ...@@ -239,26 +238,4 @@ public abstract class AsynchronousChannelProvider {
*/ */
public abstract AsynchronousSocketChannel openAsynchronousSocketChannel public abstract AsynchronousSocketChannel openAsynchronousSocketChannel
(AsynchronousChannelGroup group) throws IOException; (AsynchronousChannelGroup group) throws IOException;
/**
* Opens an asynchronous datagram channel.
*
* @param family
* The protocol family, or {@code null} for the default protocol
* family
* @param group
* The group to which the channel is bound, or {@code null} to
* bind to the default group
*
* @return The new channel
*
* @throws IllegalChannelGroupException
* If the provider that created the group differs from this provider
* @throws ShutdownChannelGroupException
* The group is shutdown
* @throws IOException
* If an I/O error occurs
*/
public abstract AsynchronousDatagramChannel openAsynchronousDatagramChannel
(ProtocolFamily family, AsynchronousChannelGroup group) throws IOException;
} }
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. 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.security;
import java.util.Set;
/**
* This interface specifies constraints for cryptographic algorithms,
* keys (key sizes), and other algorithm parameters.
* <p>
* {@code AlgorithmConstraints} objects are immutable. An implementation
* of this interface should not provide methods that can change the state
* of an instance once it has been created.
* <p>
* Note that {@code AlgorithmConstraints} can be used to represent the
* restrictions described by the security properties
* {@code jdk.certpath.disabledAlgorithms} and
* {@code jdk.tls.disabledAlgorithms}, or could be used by a
* concrete {@code PKIXCertPathChecker} to check whether a specified
* certificate in the certification path contains the required algorithm
* constraints.
*
* @see javax.net.ssl.SSLParameters#getAlgorithmConstraints
* @see javax.net.ssl.SSLParameters#setAlgorithmConstraints(AlgorithmConstraints)
*
* @since 1.7
*/
public interface AlgorithmConstraints {
/**
* Determines whether an algorithm is granted permission for the
* specified cryptographic primitives.
*
* @param primitives a set of cryptographic primitives
* @param algorithm the algorithm name
* @param parameters the algorithm parameters, or null if no additional
* parameters
*
* @return true if the algorithm is permitted and can be used for all
* of the specified cryptographic primitives
*
* @throws IllegalArgumentException if primitives or algorithm is null
* or empty
*/
public boolean permits(Set<CryptoPrimitive> primitives,
String algorithm, AlgorithmParameters parameters);
/**
* Determines whether a key is granted permission for the specified
* cryptographic primitives.
* <p>
* This method is usually used to check key size and key usage.
*
* @param primitives a set of cryptographic primitives
* @param key the key
*
* @return true if the key can be used for all of the specified
* cryptographic primitives
*
* @throws IllegalArgumentException if primitives is null or empty,
* or the key is null
*/
public boolean permits(Set<CryptoPrimitive> primitives, Key key);
/**
* Determines whether an algorithm and the corresponding key are granted
* permission for the specified cryptographic primitives.
*
* @param primitives a set of cryptographic primitives
* @param algorithm the algorithm name
* @param key the key
* @param parameters the algorithm parameters, or null if no additional
* parameters
*
* @return true if the key and the algorithm can be used for all of the
* specified cryptographic primitives
*
* @throws IllegalArgumentException if primitives or algorithm is null
* or empty, or the key is null
*/
public boolean permits(Set<CryptoPrimitive> primitives,
String algorithm, Key key, AlgorithmParameters parameters);
}
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. 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.security;
/**
* An enumeration of cryptographic primitives.
*
* @since 1.7
*/
public enum CryptoPrimitive {
/**
* Hash function
*/
MESSAGE_DIGEST,
/**
* Cryptographic random number generator
*/
SECURE_RANDOM,
/**
* Symmetric primitive: block cipher
*/
BLOCK_CIPHER,
/**
* Symmetric primitive: stream cipher
*/
STREAM_CIPHER,
/**
* Symmetric primitive: message authentication code
*/
MAC,
/**
* Symmetric primitive: key wrap
*/
KEY_WRAP,
/**
* Asymmetric primitive: public key encryption
*/
PUBLIC_KEY_ENCRYPTION,
/**
* Asymmetric primitive: signature scheme
*/
SIGNATURE,
/**
* Asymmetric primitive: key encapsulation mechanism
*/
KEY_ENCAPSULATION,
/**
* Asymmetric primitive: key agreement and key distribution
*/
KEY_AGREEMENT
}
...@@ -44,11 +44,12 @@ import java.io.Serializable; ...@@ -44,11 +44,12 @@ import java.io.Serializable;
import java.lang.ref.SoftReference; import java.lang.ref.SoftReference;
import java.text.spi.DateFormatSymbolsProvider; import java.text.spi.DateFormatSymbolsProvider;
import java.util.Arrays; import java.util.Arrays;
import java.util.Hashtable;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import java.util.TimeZone; import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.spi.LocaleServiceProvider; import java.util.spi.LocaleServiceProvider;
import sun.util.LocaleServiceProviderPool; import sun.util.LocaleServiceProviderPool;
import sun.util.TimeZoneNameUtility; import sun.util.TimeZoneNameUtility;
...@@ -321,20 +322,64 @@ public class DateFormatSymbols implements Serializable, Cloneable { ...@@ -321,20 +322,64 @@ public class DateFormatSymbols implements Serializable, Cloneable {
* @since 1.6 * @since 1.6
*/ */
public static final DateFormatSymbols getInstance(Locale locale) { public static final DateFormatSymbols getInstance(Locale locale) {
DateFormatSymbols dfs = getProviderInstance(locale);
if (dfs != null) {
return dfs;
}
return (DateFormatSymbols) getCachedInstance(locale).clone();
}
/**
* Returns a DateFormatSymbols provided by a provider or found in
* the cache. Note that this method returns a cached instance,
* not its clone. Therefore, the instance should never be given to
* an application.
*/
static final DateFormatSymbols getInstanceRef(Locale locale) {
DateFormatSymbols dfs = getProviderInstance(locale);
if (dfs != null) {
return dfs;
}
return getCachedInstance(locale);
}
private static DateFormatSymbols getProviderInstance(Locale locale) {
DateFormatSymbols providersInstance = null;
// Check whether a provider can provide an implementation that's closer // Check whether a provider can provide an implementation that's closer
// to the requested locale than what the Java runtime itself can provide. // to the requested locale than what the Java runtime itself can provide.
LocaleServiceProviderPool pool = LocaleServiceProviderPool pool =
LocaleServiceProviderPool.getPool(DateFormatSymbolsProvider.class); LocaleServiceProviderPool.getPool(DateFormatSymbolsProvider.class);
if (pool.hasProviders()) { if (pool.hasProviders()) {
DateFormatSymbols providersInstance = pool.getLocalizedObject( providersInstance = pool.getLocalizedObject(
DateFormatSymbolsGetter.INSTANCE, locale); DateFormatSymbolsGetter.INSTANCE, locale);
if (providersInstance != null) { }
return providersInstance; return providersInstance;
}
/**
* Returns a cached DateFormatSymbols if it's found in the
* cache. Otherwise, this method returns a newly cached instance
* for the given locale.
*/
private static DateFormatSymbols getCachedInstance(Locale locale) {
SoftReference<DateFormatSymbols> ref = cachedInstances.get(locale);
DateFormatSymbols dfs = null;
if (ref == null || (dfs = ref.get()) == null) {
dfs = new DateFormatSymbols(locale);
ref = new SoftReference<DateFormatSymbols>(dfs);
SoftReference<DateFormatSymbols> x = cachedInstances.putIfAbsent(locale, ref);
if (x != null) {
DateFormatSymbols y = x.get();
if (y != null) {
dfs = y;
} else {
// Replace the empty SoftReference with ref.
cachedInstances.put(locale, ref);
}
} }
} }
return dfs;
return new DateFormatSymbols(locale);
} }
/** /**
...@@ -597,56 +642,44 @@ public class DateFormatSymbols implements Serializable, Cloneable { ...@@ -597,56 +642,44 @@ public class DateFormatSymbols implements Serializable, Cloneable {
static final int millisPerHour = 60*60*1000; static final int millisPerHour = 60*60*1000;
/** /**
* Cache to hold the FormatData and TimeZoneNames ResourceBundles * Cache to hold DateFormatSymbols instances per Locale.
* of a Locale.
*/ */
private static Hashtable cachedLocaleData = new Hashtable(3); private static final ConcurrentMap<Locale, SoftReference<DateFormatSymbols>> cachedInstances
= new ConcurrentHashMap<Locale, SoftReference<DateFormatSymbols>>(3);
/** private void initializeData(Locale desiredLocale) {
* Look up resource data for the desiredLocale in the cache; update the locale = desiredLocale;
* cache if necessary.
*/ // Copy values of a cached instance if any.
private static ResourceBundle cacheLookup(Locale desiredLocale) { SoftReference<DateFormatSymbols> ref = cachedInstances.get(locale);
ResourceBundle rb; DateFormatSymbols dfs;
SoftReference data if (ref != null && (dfs = ref.get()) != null) {
= (SoftReference)cachedLocaleData.get(desiredLocale); copyMembers(dfs, this);
if (data == null) { return;
rb = LocaleData.getDateFormatData(desiredLocale);
data = new SoftReference(rb);
cachedLocaleData.put(desiredLocale, data);
} else {
if ((rb = (ResourceBundle)data.get()) == null) {
rb = LocaleData.getDateFormatData(desiredLocale);
data = new SoftReference(rb);
}
} }
return rb;
}
private void initializeData(Locale desiredLocale) { // Initialize the fields from the ResourceBundle for locale.
int i; ResourceBundle resource = LocaleData.getDateFormatData(locale);
ResourceBundle resource = cacheLookup(desiredLocale);
// FIXME: cache only ResourceBundle. Hence every time, will do eras = resource.getStringArray("Eras");
// getObject(). This won't be necessary if the Resource itself
// is cached.
eras = (String[])resource.getObject("Eras");
months = resource.getStringArray("MonthNames"); months = resource.getStringArray("MonthNames");
shortMonths = resource.getStringArray("MonthAbbreviations"); shortMonths = resource.getStringArray("MonthAbbreviations");
String[] lWeekdays = resource.getStringArray("DayNames");
weekdays = new String[8];
weekdays[0] = ""; // 1-based
for (i=0; i<lWeekdays.length; i++)
weekdays[i+1] = lWeekdays[i];
String[] sWeekdays = resource.getStringArray("DayAbbreviations");
shortWeekdays = new String[8];
shortWeekdays[0] = ""; // 1-based
for (i=0; i<sWeekdays.length; i++)
shortWeekdays[i+1] = sWeekdays[i];
ampms = resource.getStringArray("AmPmMarkers"); ampms = resource.getStringArray("AmPmMarkers");
localPatternChars = resource.getString("DateTimePatternChars"); localPatternChars = resource.getString("DateTimePatternChars");
locale = desiredLocale; // Day of week names are stored in a 1-based array.
weekdays = toOneBasedArray(resource.getStringArray("DayNames"));
shortWeekdays = toOneBasedArray(resource.getStringArray("DayAbbreviations"));
}
private static String[] toOneBasedArray(String[] src) {
int len = src.length;
String[] dst = new String[len + 1];
dst[0] = "";
for (int i = 0; i < len; i++) {
dst[i + 1] = src[i];
}
return dst;
} }
/** /**
......
/* /*
* Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 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
...@@ -46,9 +46,10 @@ import java.math.BigInteger; ...@@ -46,9 +46,10 @@ import java.math.BigInteger;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Currency; import java.util.Currency;
import java.util.Hashtable;
import java.util.Locale; import java.util.Locale;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import sun.util.resources.LocaleData; import sun.util.resources.LocaleData;
...@@ -394,14 +395,14 @@ public class DecimalFormat extends NumberFormat { ...@@ -394,14 +395,14 @@ public class DecimalFormat extends NumberFormat {
public DecimalFormat() { public DecimalFormat() {
Locale def = Locale.getDefault(Locale.Category.FORMAT); Locale def = Locale.getDefault(Locale.Category.FORMAT);
// try to get the pattern from the cache // try to get the pattern from the cache
String pattern = (String) cachedLocaleData.get(def); String pattern = cachedLocaleData.get(def);
if (pattern == null) { /* cache miss */ if (pattern == null) { /* cache miss */
// Get the pattern for the default locale. // Get the pattern for the default locale.
ResourceBundle rb = LocaleData.getNumberFormatData(def); ResourceBundle rb = LocaleData.getNumberFormatData(def);
String[] all = rb.getStringArray("NumberPatterns"); String[] all = rb.getStringArray("NumberPatterns");
pattern = all[0]; pattern = all[0];
/* update cache */ /* update cache */
cachedLocaleData.put(def, pattern); cachedLocaleData.putIfAbsent(def, pattern);
} }
// Always applyPattern after the symbols are set // Always applyPattern after the symbols are set
...@@ -3272,5 +3273,6 @@ public class DecimalFormat extends NumberFormat { ...@@ -3272,5 +3273,6 @@ public class DecimalFormat extends NumberFormat {
/** /**
* Cache to hold the NumberPattern of a Locale. * Cache to hold the NumberPattern of a Locale.
*/ */
private static Hashtable cachedLocaleData = new Hashtable(3); private static final ConcurrentMap<Locale, String> cachedLocaleData
= new ConcurrentHashMap<Locale, String>(3);
} }
...@@ -44,13 +44,14 @@ import java.io.ObjectInputStream; ...@@ -44,13 +44,14 @@ import java.io.ObjectInputStream;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import java.util.Hashtable;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.MissingResourceException; import java.util.MissingResourceException;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import java.util.SimpleTimeZone; import java.util.SimpleTimeZone;
import java.util.TimeZone; import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import sun.util.calendar.CalendarUtils; import sun.util.calendar.CalendarUtils;
import sun.util.calendar.ZoneInfoFile; import sun.util.calendar.ZoneInfoFile;
import sun.util.resources.LocaleData; import sun.util.resources.LocaleData;
...@@ -503,14 +504,14 @@ public class SimpleDateFormat extends DateFormat { ...@@ -503,14 +504,14 @@ public class SimpleDateFormat extends DateFormat {
/** /**
* Cache to hold the DateTimePatterns of a Locale. * Cache to hold the DateTimePatterns of a Locale.
*/ */
private static Hashtable<String,String[]> cachedLocaleData private static final ConcurrentMap<String, String[]> cachedLocaleData
= new Hashtable<String,String[]>(3); = new ConcurrentHashMap<String, String[]>(3);
/** /**
* Cache NumberFormat instances with Locale key. * Cache NumberFormat instances with Locale key.
*/ */
private static Hashtable<Locale,NumberFormat> cachedNumberFormatData private static final ConcurrentMap<Locale, NumberFormat> cachedNumberFormatData
= new Hashtable<Locale,NumberFormat>(3); = new ConcurrentHashMap<Locale, NumberFormat>(3);
/** /**
* The Locale used to instantiate this * The Locale used to instantiate this
...@@ -579,7 +580,7 @@ public class SimpleDateFormat extends DateFormat { ...@@ -579,7 +580,7 @@ public class SimpleDateFormat extends DateFormat {
initializeCalendar(locale); initializeCalendar(locale);
this.pattern = pattern; this.pattern = pattern;
this.formatData = DateFormatSymbols.getInstance(locale); this.formatData = DateFormatSymbols.getInstanceRef(locale);
this.locale = locale; this.locale = locale;
initialize(locale); initialize(locale);
} }
...@@ -632,9 +633,9 @@ public class SimpleDateFormat extends DateFormat { ...@@ -632,9 +633,9 @@ public class SimpleDateFormat extends DateFormat {
dateTimePatterns = r.getStringArray("DateTimePatterns"); dateTimePatterns = r.getStringArray("DateTimePatterns");
} }
/* update cache */ /* update cache */
cachedLocaleData.put(key, dateTimePatterns); cachedLocaleData.putIfAbsent(key, dateTimePatterns);
} }
formatData = DateFormatSymbols.getInstance(loc); formatData = DateFormatSymbols.getInstanceRef(loc);
if ((timeStyle >= 0) && (dateStyle >= 0)) { if ((timeStyle >= 0) && (dateStyle >= 0)) {
Object[] dateTimeArgs = {dateTimePatterns[timeStyle], Object[] dateTimeArgs = {dateTimePatterns[timeStyle],
dateTimePatterns[dateStyle + 4]}; dateTimePatterns[dateStyle + 4]};
...@@ -665,7 +666,7 @@ public class SimpleDateFormat extends DateFormat { ...@@ -665,7 +666,7 @@ public class SimpleDateFormat extends DateFormat {
numberFormat.setGroupingUsed(false); numberFormat.setGroupingUsed(false);
/* update cache */ /* update cache */
cachedNumberFormatData.put(loc, numberFormat); cachedNumberFormatData.putIfAbsent(loc, numberFormat);
} }
numberFormat = (NumberFormat) numberFormat.clone(); numberFormat = (NumberFormat) numberFormat.clone();
...@@ -897,7 +898,7 @@ public class SimpleDateFormat extends DateFormat { ...@@ -897,7 +898,7 @@ public class SimpleDateFormat extends DateFormat {
* so we can call it from readObject(). * so we can call it from readObject().
*/ */
private void initializeDefaultCentury() { private void initializeDefaultCentury() {
calendar.setTime( new Date() ); calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add( Calendar.YEAR, -80 ); calendar.add( Calendar.YEAR, -80 );
parseAmbiguousDatesAsAfter(calendar.getTime()); parseAmbiguousDatesAsAfter(calendar.getTime());
} }
...@@ -921,7 +922,7 @@ public class SimpleDateFormat extends DateFormat { ...@@ -921,7 +922,7 @@ public class SimpleDateFormat extends DateFormat {
* @since 1.2 * @since 1.2
*/ */
public void set2DigitYearStart(Date startDate) { public void set2DigitYearStart(Date startDate) {
parseAmbiguousDatesAsAfter(startDate); parseAmbiguousDatesAsAfter(new Date(startDate.getTime()));
} }
/** /**
...@@ -934,7 +935,7 @@ public class SimpleDateFormat extends DateFormat { ...@@ -934,7 +935,7 @@ public class SimpleDateFormat extends DateFormat {
* @since 1.2 * @since 1.2
*/ */
public Date get2DigitYearStart() { public Date get2DigitYearStart() {
return defaultCenturyStart; return (Date) defaultCenturyStart.clone();
} }
/** /**
......
...@@ -176,6 +176,11 @@ public class ArrayList<E> extends AbstractList<E> ...@@ -176,6 +176,11 @@ public class ArrayList<E> extends AbstractList<E>
* @param minCapacity the desired minimum capacity * @param minCapacity the desired minimum capacity
*/ */
public void ensureCapacity(int minCapacity) { public void ensureCapacity(int minCapacity) {
if (minCapacity > 0)
ensureCapacityInternal(minCapacity);
}
private void ensureCapacityInternal(int minCapacity) {
modCount++; modCount++;
// overflow-conscious code // overflow-conscious code
if (minCapacity - elementData.length > 0) if (minCapacity - elementData.length > 0)
...@@ -403,7 +408,7 @@ public class ArrayList<E> extends AbstractList<E> ...@@ -403,7 +408,7 @@ public class ArrayList<E> extends AbstractList<E>
* @return <tt>true</tt> (as specified by {@link Collection#add}) * @return <tt>true</tt> (as specified by {@link Collection#add})
*/ */
public boolean add(E e) { public boolean add(E e) {
ensureCapacity(size + 1); // Increments modCount!! ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e; elementData[size++] = e;
return true; return true;
} }
...@@ -420,7 +425,7 @@ public class ArrayList<E> extends AbstractList<E> ...@@ -420,7 +425,7 @@ public class ArrayList<E> extends AbstractList<E>
public void add(int index, E element) { public void add(int index, E element) {
rangeCheckForAdd(index); rangeCheckForAdd(index);
ensureCapacity(size + 1); // Increments modCount!! ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1, System.arraycopy(elementData, index, elementData, index + 1,
size - index); size - index);
elementData[index] = element; elementData[index] = element;
...@@ -524,7 +529,7 @@ public class ArrayList<E> extends AbstractList<E> ...@@ -524,7 +529,7 @@ public class ArrayList<E> extends AbstractList<E>
public boolean addAll(Collection<? extends E> c) { public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray(); Object[] a = c.toArray();
int numNew = a.length; int numNew = a.length;
ensureCapacity(size + numNew); // Increments modCount ensureCapacityInternal(size + numNew); // Increments modCount
System.arraycopy(a, 0, elementData, size, numNew); System.arraycopy(a, 0, elementData, size, numNew);
size += numNew; size += numNew;
return numNew != 0; return numNew != 0;
...@@ -550,7 +555,7 @@ public class ArrayList<E> extends AbstractList<E> ...@@ -550,7 +555,7 @@ public class ArrayList<E> extends AbstractList<E>
Object[] a = c.toArray(); Object[] a = c.toArray();
int numNew = a.length; int numNew = a.length;
ensureCapacity(size + numNew); // Increments modCount ensureCapacityInternal(size + numNew); // Increments modCount
int numMoved = size - index; int numMoved = size - index;
if (numMoved > 0) if (numMoved > 0)
......
...@@ -51,6 +51,8 @@ import java.security.PrivilegedExceptionAction; ...@@ -51,6 +51,8 @@ import java.security.PrivilegedExceptionAction;
import java.security.ProtectionDomain; import java.security.ProtectionDomain;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.DateFormatSymbols; import java.text.DateFormatSymbols;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import sun.util.BuddhistCalendar; import sun.util.BuddhistCalendar;
import sun.util.calendar.ZoneInfo; import sun.util.calendar.ZoneInfo;
import sun.util.resources.LocaleData; import sun.util.resources.LocaleData;
...@@ -837,7 +839,8 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca ...@@ -837,7 +839,8 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca
* Cache to hold the firstDayOfWeek and minimalDaysInFirstWeek * Cache to hold the firstDayOfWeek and minimalDaysInFirstWeek
* of a Locale. * of a Locale.
*/ */
private static Hashtable<Locale, int[]> cachedLocaleData = new Hashtable<Locale, int[]>(3); private static final ConcurrentMap<Locale, int[]> cachedLocaleData
= new ConcurrentHashMap<Locale, int[]>(3);
// Special values of stamp[] // Special values of stamp[]
/** /**
...@@ -1022,7 +1025,7 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca ...@@ -1022,7 +1025,7 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca
// returns a BuddhistCalendar instance. // returns a BuddhistCalendar instance.
if ("th".equals(aLocale.getLanguage()) if ("th".equals(aLocale.getLanguage())
&& ("TH".equals(aLocale.getCountry()))) { && ("TH".equals(aLocale.getCountry()))) {
cal = new BuddhistCalendar(zone, aLocale); cal = new BuddhistCalendar(zone, aLocale);
} else { } else {
cal = new GregorianCalendar(zone, aLocale); cal = new GregorianCalendar(zone, aLocale);
} }
...@@ -2588,7 +2591,7 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca ...@@ -2588,7 +2591,7 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca
data = new int[2]; data = new int[2];
data[0] = Integer.parseInt(bundle.getString("firstDayOfWeek")); data[0] = Integer.parseInt(bundle.getString("firstDayOfWeek"));
data[1] = Integer.parseInt(bundle.getString("minimalDaysInFirstWeek")); data[1] = Integer.parseInt(bundle.getString("minimalDaysInFirstWeek"));
cachedLocaleData.put(desiredLocale, data); cachedLocaleData.putIfAbsent(desiredLocale, data);
} }
firstDayOfWeek = data[0]; firstDayOfWeek = data[0];
minimalDaysInFirstWeek = data[1]; minimalDaysInFirstWeek = data[1];
......
...@@ -758,7 +758,7 @@ public final class Locale implements Cloneable, Serializable { ...@@ -758,7 +758,7 @@ public final class Locale implements Cloneable, Serializable {
} }
private static void initDefault() { private static void initDefault() {
String language, region, country, variant; String language, region, script, country, variant;
language = AccessController.doPrivileged( language = AccessController.doPrivileged(
new GetPropertyAction("user.language", "en")); new GetPropertyAction("user.language", "en"));
// for compatibility, check for old user.region property // for compatibility, check for old user.region property
...@@ -774,43 +774,41 @@ public final class Locale implements Cloneable, Serializable { ...@@ -774,43 +774,41 @@ public final class Locale implements Cloneable, Serializable {
country = region; country = region;
variant = ""; variant = "";
} }
script = "";
} else { } else {
script = AccessController.doPrivileged(
new GetPropertyAction("user.script", ""));
country = AccessController.doPrivileged( country = AccessController.doPrivileged(
new GetPropertyAction("user.country", "")); new GetPropertyAction("user.country", ""));
variant = AccessController.doPrivileged( variant = AccessController.doPrivileged(
new GetPropertyAction("user.variant", "")); new GetPropertyAction("user.variant", ""));
} }
defaultLocale = getInstance(language, country, variant); defaultLocale = getInstance(language, script, country, variant, null);
} }
private static void initDefault(Locale.Category category) { private static void initDefault(Locale.Category category) {
String language, region, country, variant; // make sure defaultLocale is initialized
if (defaultLocale == null) {
initDefault();
}
Locale defaultCategoryLocale = getInstance(
AccessController.doPrivileged(
new GetPropertyAction(category.languageKey, defaultLocale.getLanguage())),
AccessController.doPrivileged(
new GetPropertyAction(category.scriptKey, defaultLocale.getScript())),
AccessController.doPrivileged(
new GetPropertyAction(category.countryKey, defaultLocale.getCountry())),
AccessController.doPrivileged(
new GetPropertyAction(category.variantKey, defaultLocale.getVariant())),
null);
switch (category) { switch (category) {
case DISPLAY: case DISPLAY:
language = AccessController.doPrivileged( defaultDisplayLocale = defaultCategoryLocale;
new GetPropertyAction("user.language.display", ""));
if ("".equals(language)) {
defaultDisplayLocale = getDefault();
} else {
country = AccessController.doPrivileged(
new GetPropertyAction("user.country.display", ""));
variant = AccessController.doPrivileged(
new GetPropertyAction("user.variant.display", ""));
defaultDisplayLocale = getInstance(language, country, variant);
}
break; break;
case FORMAT: case FORMAT:
language = AccessController.doPrivileged( defaultFormatLocale = defaultCategoryLocale;
new GetPropertyAction("user.language.format", ""));
if ("".equals(language)) {
defaultFormatLocale = getDefault();
} else {
country = AccessController.doPrivileged(
new GetPropertyAction("user.country.format", ""));
variant = AccessController.doPrivileged(
new GetPropertyAction("user.variant.format", ""));
defaultFormatLocale = getInstance(language, country, variant);
}
break; break;
} }
} }
...@@ -2124,13 +2122,31 @@ public final class Locale implements Cloneable, Serializable { ...@@ -2124,13 +2122,31 @@ public final class Locale implements Cloneable, Serializable {
* Category used to represent the default locale for * Category used to represent the default locale for
* displaying user interfaces. * displaying user interfaces.
*/ */
DISPLAY, DISPLAY("user.language.display",
"user.script.display",
"user.country.display",
"user.variant.display"),
/** /**
* Category used to represent the default locale for * Category used to represent the default locale for
* formatting dates, numbers, and/or currencies. * formatting dates, numbers, and/or currencies.
*/ */
FORMAT, FORMAT("user.language.format",
"user.script.format",
"user.country.format",
"user.variant.format");
Category(String languageKey, String scriptKey, String countryKey, String variantKey) {
this.languageKey = languageKey;
this.scriptKey = scriptKey;
this.countryKey = countryKey;
this.variantKey = variantKey;
}
final String languageKey;
final String scriptKey;
final String countryKey;
final String variantKey;
} }
/** /**
......
...@@ -160,11 +160,6 @@ abstract public class TimeZone implements Serializable, Cloneable { ...@@ -160,11 +160,6 @@ abstract public class TimeZone implements Serializable, Cloneable {
private static final int ONE_HOUR = 60*ONE_MINUTE; private static final int ONE_HOUR = 60*ONE_MINUTE;
private static final int ONE_DAY = 24*ONE_HOUR; private static final int ONE_DAY = 24*ONE_HOUR;
/**
* Cache to hold the SimpleDateFormat objects for a Locale.
*/
private static Hashtable cachedLocaleData = new Hashtable(3);
// Proclaim serialization compatibility with JDK 1.1 // Proclaim serialization compatibility with JDK 1.1
static final long serialVersionUID = 3581463369166924961L; static final long serialVersionUID = 3581463369166924961L;
......
...@@ -222,8 +222,10 @@ public class Vector<E> ...@@ -222,8 +222,10 @@ public class Vector<E>
* @param minCapacity the desired minimum capacity * @param minCapacity the desired minimum capacity
*/ */
public synchronized void ensureCapacity(int minCapacity) { public synchronized void ensureCapacity(int minCapacity) {
modCount++; if (minCapacity > 0) {
ensureCapacityHelper(minCapacity); modCount++;
ensureCapacityHelper(minCapacity);
}
} }
/** /**
......
...@@ -529,8 +529,6 @@ public class LogRecord implements java.io.Serializable { ...@@ -529,8 +529,6 @@ public class LogRecord implements java.io.Serializable {
Throwable throwable = new Throwable(); Throwable throwable = new Throwable();
int depth = access.getStackTraceDepth(throwable); int depth = access.getStackTraceDepth(throwable);
String logClassName = "java.util.logging.Logger";
String plogClassName = "sun.util.logging.PlatformLogger";
boolean lookingForLogger = true; boolean lookingForLogger = true;
for (int ix = 0; ix < depth; ix++) { for (int ix = 0; ix < depth; ix++) {
// Calling getStackTraceElement directly prevents the VM // Calling getStackTraceElement directly prevents the VM
...@@ -538,13 +536,14 @@ public class LogRecord implements java.io.Serializable { ...@@ -538,13 +536,14 @@ public class LogRecord implements java.io.Serializable {
StackTraceElement frame = StackTraceElement frame =
access.getStackTraceElement(throwable, ix); access.getStackTraceElement(throwable, ix);
String cname = frame.getClassName(); String cname = frame.getClassName();
boolean isLoggerImpl = isLoggerImplFrame(cname);
if (lookingForLogger) { if (lookingForLogger) {
// Skip all frames until we have found the first logger frame. // Skip all frames until we have found the first logger frame.
if (cname.equals(logClassName) || cname.startsWith(plogClassName)) { if (isLoggerImpl) {
lookingForLogger = false; lookingForLogger = false;
} }
} else { } else {
if (!cname.equals(logClassName) && !cname.startsWith(plogClassName)) { if (!isLoggerImpl) {
// skip reflection call // skip reflection call
if (!cname.startsWith("java.lang.reflect.") && !cname.startsWith("sun.reflect.")) { if (!cname.startsWith("java.lang.reflect.") && !cname.startsWith("sun.reflect.")) {
// We've found the relevant frame. // We've found the relevant frame.
...@@ -558,4 +557,11 @@ public class LogRecord implements java.io.Serializable { ...@@ -558,4 +557,11 @@ public class LogRecord implements java.io.Serializable {
// We haven't found a suitable frame, so just punt. This is // We haven't found a suitable frame, so just punt. This is
// OK as we are only committed to making a "best effort" here. // OK as we are only committed to making a "best effort" here.
} }
private boolean isLoggerImplFrame(String cname) {
// the log record could be created for a platform logger
return (cname.equals("java.util.logging.Logger") ||
cname.startsWith("java.util.logging.LoggingProxyImpl") ||
cname.startsWith("sun.util.logging."));
}
} }
...@@ -211,8 +211,8 @@ import java.util.Map; ...@@ -211,8 +211,8 @@ import java.util.Map;
* reverse DNS name of the organization that specifies the MBeans, * reverse DNS name of the organization that specifies the MBeans,
* followed by a period and a string whose interpretation is * followed by a period and a string whose interpretation is
* determined by that organization. For example, MBeans specified by * determined by that organization. For example, MBeans specified by
* Sun Microsystems Inc., DNS name <code>sun.com</code>, would have * <code>example.com</code> would have
* domains such as <code>com.sun.MyDomain</code>. This is essentially * domains such as <code>com.example.MyDomain</code>. This is essentially
* the same convention as for Java-language package names.</p> * the same convention as for Java-language package names.</p>
* *
* <p>The <b>serialVersionUID</b> of this class is <code>1081892073854801359L</code>. * <p>The <b>serialVersionUID</b> of this class is <code>1081892073854801359L</code>.
......
...@@ -35,18 +35,18 @@ ...@@ -35,18 +35,18 @@
. Please also read the important comment on basedir definition below. . Please also read the important comment on basedir definition below.
--> -->
<project name="JMX API Version 1.4 - Java SE 6 implementation" <project name="JMX API Version 1.4 - Java SE 6 implementation"
default="jar" default="jar"
basedir="../../../../.." basedir="../../../../.."
> >
<!-- IMPORTANT: BASEDIR DEFINITION <!-- IMPORTANT: BASEDIR DEFINITION
This file is assumed to be in: This file is assumed to be in:
<src_bundle_dir>/j2se/src/share/classes/javax/management <src_bundle_dir>/j2se/src/share/classes/javax/management
Thus the basedir for this project is defined above as: Thus the basedir for this project is defined above as:
basedir="../../../../.." basedir="../../../../.."
in order to be the parent dir of src subdir. in order to be the parent dir of src subdir.
Result of the build will be placed in ${basedir}/build_jmx Result of the build will be placed in ${basedir}/build_jmx
as defined by ${dir.build} property below. as defined by ${dir.build} property below.
--> -->
...@@ -163,14 +163,14 @@ ...@@ -163,14 +163,14 @@
<echo message=" BUILD_DATE = ${BUILD_DATE}" /> <echo message=" BUILD_DATE = ${BUILD_DATE}" />
</target> </target>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- Call classes subtargets and rmic stubs generation --> <!-- Call classes subtargets and rmic stubs generation -->
<target name="classes" depends="init,classes-javac,classes-rmic" <target name="classes" depends="init,classes-javac,classes-rmic"
description="Call classes subtargets and rmic stubs generation" description="Call classes subtargets and rmic stubs generation"
/> />
...@@ -183,13 +183,13 @@ ...@@ -183,13 +183,13 @@
<mkdir dir="${dir.build.classes}" /> <mkdir dir="${dir.build.classes}" />
<javac srcdir="${dir.src}" <javac srcdir="${dir.src}"
destdir="${dir.build.classes}" destdir="${dir.build.classes}"
source="${flag.javac.source}" source="${flag.javac.source}"
debug="${flag.debug}" debug="${flag.debug}"
debuglevel="${flag.debug.level}" debuglevel="${flag.debug.level}"
optimize="${flag.optimize}" optimize="${flag.optimize}"
includeAntRuntime="no" includeAntRuntime="no"
includeJavaRuntime="no" includeJavaRuntime="no"
> >
<include name="javax/management/**"/> <include name="javax/management/**"/>
<include name="com/sun/jmx/**"/> <include name="com/sun/jmx/**"/>
...@@ -253,7 +253,7 @@ ...@@ -253,7 +253,7 @@
<mkdir dir="${dir.build.lib}" /> <mkdir dir="${dir.build.lib}" />
<jar jarfile="${dir.build.lib}/jmx.jar" <jar jarfile="${dir.build.lib}/jmx.jar"
update="true" update="true"
> >
...@@ -269,10 +269,10 @@ ...@@ -269,10 +269,10 @@
<attribute name="Sealed" value="true" /> <attribute name="Sealed" value="true" />
<attribute name="Specification-Title" value="JMX(TM) API" /> <attribute name="Specification-Title" value="JMX(TM) API" />
<attribute name="Specification-Version" value="1.4" /> <attribute name="Specification-Version" value="1.4" />
<attribute name="Specification-Vendor" value="Sun Microsystems, Inc." /> <attribute name="Specification-Vendor" value="Oracle Corporation" />
<attribute name="Implementation-Title" value="JMX(TM) API, Java SE 6 implementation" /> <attribute name="Implementation-Title" value="JMX(TM) API, Java SE 6 implementation" />
<attribute name="Implementation-Version" value="${BUILD_DATE} rebuild of Mustang JMX sources" /> <attribute name="Implementation-Version" value="${BUILD_DATE} rebuild of Java SE JMX sources" />
<attribute name="Implementation-Vendor" value="Source bundle from Sun Microsystems, Inc. - Customer rebuilt" /> <attribute name="Implementation-Vendor" value="Source bundle from Oracle Corporation - Customer rebuilt" />
</section> </section>
</manifest> </manifest>
</jar> </jar>
...@@ -295,16 +295,16 @@ ...@@ -295,16 +295,16 @@
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- Delete build directory and all its contents --> <!-- Delete build directory and all its contents -->
<target name="clean-all" <target name="clean-all"
description="Delete build directory and all its contents" > description="Delete build directory and all its contents" >
<delete dir="${dir.build}" /> <delete dir="${dir.build}" />
</target> </target>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- Clean all and build everything --> <!-- Clean all and build everything -->
<target name="all" depends="clean-all,jar" <target name="all" depends="clean-all,jar"
description="Clean all and build everything" /> description="Clean all and build everything" />
......
...@@ -92,8 +92,6 @@ import javax.management.RuntimeOperationsException; ...@@ -92,8 +92,6 @@ import javax.management.RuntimeOperationsException;
* @since 1.5 * @since 1.5
*/ */
// Sun Microsystems, Sept. 2002: Revisited for JMX 1.2 (DF)
//
@SuppressWarnings("serial") // serialVersionUID is not constant @SuppressWarnings("serial") // serialVersionUID is not constant
public class ModelMBeanNotificationInfo public class ModelMBeanNotificationInfo
extends MBeanNotificationInfo extends MBeanNotificationInfo
......
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. 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 javax.net.ssl;
/**
* Extends the <code>SSLSession</code> interface to support additional
* session attributes.
*
* @since 1.7
*/
public abstract class ExtendedSSLSession implements SSLSession {
/**
* Obtains an array of supported signature algorithms that the local side
* is willing to use.
* <p>
* Note: this method is used to indicate to the peer which signature
* algorithms may be used for digital signatures in TLS 1.2. It is
* not meaningful for TLS versions prior to 1.2.
* <p>
* The signature algorithm name must be a standard Java Security
* name (such as "SHA1withRSA", "SHA256withECDSA", and so on).
* See Appendix A in the <a href=
* "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
* Java Cryptography Architecture API Specification &amp; Reference </a>
* for information about standard algorithm names.
* <p>
* Note: the local supported signature algorithms should conform to
* the algorithm constraints specified by
* {@link SSLParameters#getAlgorithmConstraints getAlgorithmConstraints()}
* method in <code>SSLParameters</code>.
*
* @return An array of supported signature algorithms, in descending
* order of preference. The return value is an empty array if
* no signature algorithm is supported.
*
* @see SSLParameters#getAlgorithmConstraints
*/
public abstract String[] getLocalSupportedSignatureAlgorithms();
/**
* Obtains an array of supported signature algorithms that the peer is
* able to use.
* <p>
* Note: this method is used to indicate to the local side which signature
* algorithms may be used for digital signatures in TLS 1.2. It is
* not meaningful for TLS versions prior to 1.2.
* <p>
* The signature algorithm name must be a standard Java Security
* name (such as "SHA1withRSA", "SHA256withECDSA", and so on).
* See Appendix A in the <a href=
* "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
* Java Cryptography Architecture API Specification &amp; Reference </a>
* for information about standard algorithm names.
*
* @return An array of supported signature algorithms, in descending
* order of preference. The return value is an empty array if
* the peer has not sent the supported signature algorithms.
*
* @see X509KeyManager
* @see X509ExtendedKeyManager
*/
public abstract String[] getPeerSupportedSignatureAlgorithms();
}
/* /*
* Copyright (c) 1999, 2005, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * 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
...@@ -188,19 +188,8 @@ class HttpsURLConnection extends HttpURLConnection ...@@ -188,19 +188,8 @@ class HttpsURLConnection extends HttpURLConnection
* <p> * <p>
* The default implementation will deny such connections. * The default implementation will deny such connections.
*/ */
private static HostnameVerifier defaultHostnameVerifier; private static HostnameVerifier defaultHostnameVerifier =
new DefaultHostnameVerifier();
/**
* Initialize the default <code>HostnameVerifier</code>.
*/
static {
try {
defaultHostnameVerifier =
new sun.net.www.protocol.https.DefaultHostnameVerifier();
} catch (NoClassDefFoundError e) {
defaultHostnameVerifier = new DefaultHostnameVerifier();
}
}
/* /*
* The initial default <code>HostnameVerifier</code>. Should be * The initial default <code>HostnameVerifier</code>. Should be
......
/* /*
* Copyright (c) 2003, 2006, 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
...@@ -967,6 +967,47 @@ public abstract class SSLEngine { ...@@ -967,6 +967,47 @@ public abstract class SSLEngine {
public abstract SSLSession getSession(); public abstract SSLSession getSession();
/**
* Returns the {@code SSLSession} being constructed during a SSL/TLS
* handshake.
* <p>
* TLS protocols may negotiate parameters that are needed when using
* an instance of this class, but before the {@code SSLSession} has
* been completely initialized and made available via {@code getSession}.
* For example, the list of valid signature algorithms may restrict
* the type of certificates that can used during TrustManager
* decisions, or the maximum TLS fragment packet sizes can be
* resized to better support the network environment.
* <p>
* This method provides early access to the {@code SSLSession} being
* constructed. Depending on how far the handshake has progressed,
* some data may not yet be available for use. For example, if a
* remote server will be sending a Certificate chain, but that chain
* has yet not been processed, the {@code getPeerCertificates}
* method of {@code SSLSession} will throw a
* SSLPeerUnverifiedException. Once that chain has been processed,
* {@code getPeerCertificates} will return the proper value.
*
* @see SSLSocket
* @see SSLSession
* @see ExtendedSSLSession
* @see X509ExtendedKeyManager
* @see X509ExtendedTrustManager
*
* @return null if this instance is not currently handshaking, or
* if the current handshake has not progressed far enough to
* create a basic SSLSession. Otherwise, this method returns the
* {@code SSLSession} currently being negotiated.
* @throws UnsupportedOperationException if the underlying provider
* does not implement the operation.
*
* @since 1.7
*/
public SSLSession getHandshakeSession() {
throw new UnsupportedOperationException();
}
/** /**
* Initiates handshaking (initial or renegotiation) on this SSLEngine. * Initiates handshaking (initial or renegotiation) on this SSLEngine.
* <P> * <P>
......
/* /*
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 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
...@@ -25,24 +25,29 @@ ...@@ -25,24 +25,29 @@
package javax.net.ssl; package javax.net.ssl;
import java.security.AlgorithmConstraints;
/** /**
* Encapsulates parameters for an SSL/TLS connection. The parameters * Encapsulates parameters for an SSL/TLS connection. The parameters
* are the list of ciphersuites to be accepted in an SSL/TLS handshake, * are the list of ciphersuites to be accepted in an SSL/TLS handshake,
* the list of protocols to be allowed, and whether SSL/TLS servers should * the list of protocols to be allowed, the endpoint identification
* request or require client authentication. * algorithm during SSL/TLS handshaking, the algorithm constraints and
* * whether SSL/TLS servers should request or require client authentication.
* <p>SSLParameters can be created via the constructors in this class. * <p>
* SSLParameters can be created via the constructors in this class.
* Objects can also be obtained using the <code>getSSLParameters()</code> * Objects can also be obtained using the <code>getSSLParameters()</code>
* methods in * methods in
* {@link SSLSocket#getSSLParameters SSLSocket} and * {@link SSLSocket#getSSLParameters SSLSocket} and
* {@link SSLServerSocket#getSSLParameters SSLServerSocket} and
* {@link SSLEngine#getSSLParameters SSLEngine} or the * {@link SSLEngine#getSSLParameters SSLEngine} or the
* {@link SSLContext#getDefaultSSLParameters getDefaultSSLParameters()} and * {@link SSLContext#getDefaultSSLParameters getDefaultSSLParameters()} and
* {@link SSLContext#getSupportedSSLParameters getSupportedSSLParameters()} * {@link SSLContext#getSupportedSSLParameters getSupportedSSLParameters()}
* methods in <code>SSLContext</code>. * methods in <code>SSLContext</code>.
* * <p>
* <P>SSLParameters can be applied to a connection via the methods * SSLParameters can be applied to a connection via the methods
* {@link SSLSocket#setSSLParameters SSLSocket.setSSLParameters()} and * {@link SSLSocket#setSSLParameters SSLSocket.setSSLParameters()} and
* {@link SSLEngine#setSSLParameters SSLEngine.getSSLParameters()}. * {@link SSLServerSocket#setSSLParameters SSLServerSocket.setSSLParameters()}
* and {@link SSLEngine#setSSLParameters SSLEngine.getSSLParameters()}.
* *
* @see SSLSocket * @see SSLSocket
* @see SSLEngine * @see SSLEngine
...@@ -56,11 +61,13 @@ public class SSLParameters { ...@@ -56,11 +61,13 @@ public class SSLParameters {
private String[] protocols; private String[] protocols;
private boolean wantClientAuth; private boolean wantClientAuth;
private boolean needClientAuth; private boolean needClientAuth;
private String identificationAlgorithm;
private AlgorithmConstraints algorithmConstraints;
/** /**
* Constructs SSLParameters. * Constructs SSLParameters.
* * <p>
* <p>The cipherSuites and protocols values are set to <code>null</code>, * The cipherSuites and protocols values are set to <code>null</code>,
* wantClientAuth and needClientAuth are set to <code>false</code>. * wantClientAuth and needClientAuth are set to <code>false</code>.
*/ */
public SSLParameters() { public SSLParameters() {
...@@ -69,6 +76,7 @@ public class SSLParameters { ...@@ -69,6 +76,7 @@ public class SSLParameters {
/** /**
* Constructs SSLParameters from the specified array of ciphersuites. * Constructs SSLParameters from the specified array of ciphersuites.
* <p>
* Calling this constructor is equivalent to calling the no-args * Calling this constructor is equivalent to calling the no-args
* constructor followed by * constructor followed by
* <code>setCipherSuites(cipherSuites);</code>. * <code>setCipherSuites(cipherSuites);</code>.
...@@ -82,6 +90,7 @@ public class SSLParameters { ...@@ -82,6 +90,7 @@ public class SSLParameters {
/** /**
* Constructs SSLParameters from the specified array of ciphersuites * Constructs SSLParameters from the specified array of ciphersuites
* and protocols. * and protocols.
* <p>
* Calling this constructor is equivalent to calling the no-args * Calling this constructor is equivalent to calling the no-args
* constructor followed by * constructor followed by
* <code>setCipherSuites(cipherSuites); setProtocols(protocols);</code>. * <code>setCipherSuites(cipherSuites); setProtocols(protocols);</code>.
...@@ -178,4 +187,71 @@ public class SSLParameters { ...@@ -178,4 +187,71 @@ public class SSLParameters {
this.needClientAuth = needClientAuth; this.needClientAuth = needClientAuth;
} }
/**
* Returns the cryptographic algorithm constraints.
*
* @return the cryptographic algorithm constraints, or null if the
* constraints have not been set
*
* @see #setAlgorithmConstraints(AlgorithmConstraints)
*
* @since 1.7
*/
public AlgorithmConstraints getAlgorithmConstraints() {
return algorithmConstraints;
}
/**
* Sets the cryptographic algorithm constraints, which will be used
* in addition to any configured by the runtime environment.
* <p>
* If the <code>constraints</code> parameter is non-null, every
* cryptographic algorithm, key and algorithm parameters used in the
* SSL/TLS handshake must be permitted by the constraints.
*
* @param constraints the algorithm constraints (or null)
*
* @since 1.7
*/
public void setAlgorithmConstraints(AlgorithmConstraints constraints) {
// the constraints object is immutable
this.algorithmConstraints = constraints;
}
/**
* Gets the endpoint identification algorithm.
*
* @return the endpoint identification algorithm, or null if none
* has been set.
*
* @see X509ExtendedTrustManager
* @see #setEndpointIdentificationAlgorithm(String)
*
* @since 1.7
*/
public String getEndpointIdentificationAlgorithm() {
return identificationAlgorithm;
}
/**
* Sets the endpoint identification algorithm.
* <p>
* If the <code>algorithm</code> parameter is non-null or non-empty, the
* endpoint identification/verification procedures must be handled during
* SSL/TLS handshaking. This is to prevent man-in-the-middle attacks.
*
* @param algorithm The standard string name of the endpoint
* identification algorithm (or null). See Appendix A in the <a href=
* "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
* Java Cryptography Architecture API Specification &amp; Reference </a>
* for information about standard algorithm names.
*
* @see X509ExtendedTrustManager
*
* @since 1.7
*/
public void setEndpointIdentificationAlgorithm(String algorithm) {
this.identificationAlgorithm = algorithm;
}
} }
/* /*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 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
...@@ -370,6 +370,51 @@ public abstract class SSLSocket extends Socket ...@@ -370,6 +370,51 @@ public abstract class SSLSocket extends Socket
public abstract SSLSession getSession(); public abstract SSLSession getSession();
/**
* Returns the {@code SSLSession} being constructed during a SSL/TLS
* handshake.
* <p>
* TLS protocols may negotiate parameters that are needed when using
* an instance of this class, but before the {@code SSLSession} has
* been completely initialized and made available via {@code getSession}.
* For example, the list of valid signature algorithms may restrict
* the type of certificates that can used during TrustManager
* decisions, or the maximum TLS fragment packet sizes can be
* resized to better support the network environment.
* <p>
* This method provides early access to the {@code SSLSession} being
* constructed. Depending on how far the handshake has progressed,
* some data may not yet be available for use. For example, if a
* remote server will be sending a Certificate chain, but that chain
* has yet not been processed, the {@code getPeerCertificates}
* method of {@code SSLSession} will throw a
* SSLPeerUnverifiedException. Once that chain has been processed,
* {@code getPeerCertificates} will return the proper value.
* <p>
* Unlike {@link #getSession()}, this method does not initiate the
* initial handshake and does not block until handshaking is
* complete.
*
* @see SSLEngine
* @see SSLSession
* @see ExtendedSSLSession
* @see X509ExtendedKeyManager
* @see X509ExtendedTrustManager
*
* @return null if this instance is not currently handshaking, or
* if the current handshake has not progressed far enough to
* create a basic SSLSession. Otherwise, this method returns the
* {@code SSLSession} currently being negotiated.
* @throws UnsupportedOperationException if the underlying provider
* does not implement the operation.
*
* @since 1.7
*/
public SSLSession getHandshakeSession() {
throw new UnsupportedOperationException();
}
/** /**
* Registers an event listener to receive notifications that an * Registers an event listener to receive notifications that an
* SSL handshake has completed on this connection. * SSL handshake has completed on this connection.
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册