提交 9b065f45 编写于 作者: L lana

Merge

...@@ -90,3 +90,6 @@ b53f226b1d91473ac54184afa827be07b87e0319 jdk7-b112 ...@@ -90,3 +90,6 @@ b53f226b1d91473ac54184afa827be07b87e0319 jdk7-b112
61d3b9fbb26bdef56cfa41b9af5bc312a22cbeb8 jdk7-b113 61d3b9fbb26bdef56cfa41b9af5bc312a22cbeb8 jdk7-b113
e250cef36ea05e627e7e6f7d75e5e19f529e2ba3 jdk7-b114 e250cef36ea05e627e7e6f7d75e5e19f529e2ba3 jdk7-b114
449bad8d67b5808ecf0f927683acc0a5940f8c85 jdk7-b115 449bad8d67b5808ecf0f927683acc0a5940f8c85 jdk7-b115
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,
......
/* /*
* 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,
......
...@@ -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) 2007, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -23,71 +23,61 @@ ...@@ -23,71 +23,61 @@
* questions. * questions.
*/ */
package sun.java2d.pisces; package java.security;
/** /**
* The <code>LineSink</code> interface accepts a series of line * An enumeration of cryptographic primitives.
* drawing commands: <code>moveTo</code>, <code>lineTo</code>,
* <code>close</code> (equivalent to a <code>lineTo</code> command
* with an argument equal to the argument of the last
* <code>moveTo</code> command), and <code>end</code>.
*
* <p> A <code>Flattener</code> may be used to connect a general path
* source to a <code>LineSink</code>.
*
* <p> The <code>Renderer</code> class implements the
* <code>LineSink</code> interface.
* *
* @since 1.7
*/ */
public interface LineSink { public enum CryptoPrimitive {
/**
* Hash function
*/
MESSAGE_DIGEST,
/** /**
* Moves the current drawing position to the point <code>(x0, * Cryptographic random number generator
* y0)</code>.
*
* @param x0 the X coordinate
* @param y0 the Y coordinate
*/ */
public void moveTo(float x0, float y0); SECURE_RANDOM,
/** /**
* Provides a hint that the current segment should be joined to * Symmetric primitive: block cipher
* the following segment using an explicit miter or round join if
* required.
*
* <p> An application-generated path will generally have no need
* to contain calls to this method; they are typically introduced
* by a <code>Flattener</code> to mark segment divisions that
* appear in its input, and consumed by a <code>Stroker</code>
* that is responsible for emitting the miter or round join
* segments.
*
* <p> Other <code>LineSink</code> classes should simply pass this
* hint to their output sink as needed.
*/ */
public void lineJoin(); BLOCK_CIPHER,
/** /**
* Draws a line from the current drawing position to the point * Symmetric primitive: stream cipher
* <code>(x1, y1)</code> and sets the current drawing position to
* <code>(x1, y1)</code>.
*
* @param x1 the X coordinate
* @param y1 the Y coordinate
*/ */
public void lineTo(float x1, float y1); STREAM_CIPHER,
/** /**
* Closes the current path by drawing a line from the current * Symmetric primitive: message authentication code
* drawing position to the point specified by the moset recent
* <code>moveTo</code> command.
*/ */
public void close(); MAC,
/** /**
* Ends the current path. It may be necessary to end a path in * Symmetric primitive: key wrap
* order to allow end caps to be drawn.
*/ */
public void end(); 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
...@@ -56,8 +56,8 @@ import java.net.*; ...@@ -56,8 +56,8 @@ import java.net.*;
* @since 1.4 * @since 1.4
* @author David Brownell * @author David Brownell
*/ */
public abstract class SSLServerSocket extends ServerSocket public abstract class SSLServerSocket extends ServerSocket {
{
/** /**
* Used only by subclasses. * Used only by subclasses.
* <P> * <P>
...@@ -449,8 +449,79 @@ public abstract class SSLServerSocket extends ServerSocket ...@@ -449,8 +449,79 @@ public abstract class SSLServerSocket extends ServerSocket
* *
* @return true indicates that sessions may be created; this * @return true indicates that sessions may be created; this
* is the default. false indicates that an existing * is the default. false indicates that an existing
* session must be resumed. * session must be resumed
* @see #setEnableSessionCreation(boolean) * @see #setEnableSessionCreation(boolean)
*/ */
public abstract boolean getEnableSessionCreation(); public abstract boolean getEnableSessionCreation();
/**
* Returns the SSLParameters in effect for newly accepted connections.
* The ciphersuites and protocols of the returned SSLParameters
* are always non-null.
*
* @return the SSLParameters in effect for newly accepted connections
*
* @see #setSSLParameters(SSLParameters)
*
* @since 1.7
*/
public SSLParameters getSSLParameters() {
SSLParameters parameters = new SSLParameters();
parameters.setCipherSuites(getEnabledCipherSuites());
parameters.setProtocols(getEnabledProtocols());
if (getNeedClientAuth()) {
parameters.setNeedClientAuth(true);
} else if (getWantClientAuth()) {
parameters.setWantClientAuth(true);
}
return parameters;
}
/**
* Applies SSLParameters to newly accepted connections.
*
* <p>This means:
* <ul>
* <li>if <code>params.getCipherSuites()</code> is non-null,
* <code>setEnabledCipherSuites()</code> is called with that value
* <li>if <code>params.getProtocols()</code> is non-null,
* <code>setEnabledProtocols()</code> is called with that value
* <li>if <code>params.getNeedClientAuth()</code> or
* <code>params.getWantClientAuth()</code> return <code>true</code>,
* <code>setNeedClientAuth(true)</code> and
* <code>setWantClientAuth(true)</code> are called, respectively;
* otherwise <code>setWantClientAuth(false)</code> is called.
* </ul>
*
* @param params the parameters
* @throws IllegalArgumentException if the setEnabledCipherSuites() or
* the setEnabledProtocols() call fails
*
* @see #getSSLParameters()
*
* @since 1.7
*/
public void setSSLParameters(SSLParameters params) {
String[] s;
s = params.getCipherSuites();
if (s != null) {
setEnabledCipherSuites(s);
}
s = params.getProtocols();
if (s != null) {
setEnabledProtocols(s);
}
if (params.getNeedClientAuth()) {
setNeedClientAuth(true);
} else if (params.getWantClientAuth()) {
setWantClientAuth(true);
} else {
setWantClientAuth(false);
}
}
} }
/* /*
* 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
...@@ -30,6 +30,7 @@ import java.net.*; ...@@ -30,6 +30,7 @@ import java.net.*;
import javax.net.SocketFactory; import javax.net.SocketFactory;
import java.io.IOException; import java.io.IOException;
import java.security.*; import java.security.*;
import java.util.Locale;
import sun.security.action.GetPropertyAction; import sun.security.action.GetPropertyAction;
...@@ -50,7 +51,8 @@ public abstract class SSLSocketFactory extends SocketFactory ...@@ -50,7 +51,8 @@ public abstract class SSLSocketFactory extends SocketFactory
static { static {
String s = java.security.AccessController.doPrivileged( String s = java.security.AccessController.doPrivileged(
new GetPropertyAction("javax.net.debug", "")).toLowerCase(); new GetPropertyAction("javax.net.debug", "")).toLowerCase(
Locale.ENGLISH);
DEBUG = s.contains("all") || s.contains("ssl"); DEBUG = s.contains("all") || s.contains("ssl");
} }
......
...@@ -384,7 +384,7 @@ public final class JLayer<V extends Component> ...@@ -384,7 +384,7 @@ public final class JLayer<V extends Component>
* @return true * @return true
* @see JComponent#isPaintingOrigin() * @see JComponent#isPaintingOrigin()
*/ */
boolean isPaintingOrigin() { protected boolean isPaintingOrigin() {
return true; return true;
} }
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册