+ *
* Object x = new Integer(0);
* System.out.println((String)x);
*
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/ClassLoader.java
--- a/src/share/classes/java/lang/ClassLoader.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/ClassLoader.java Thu Oct 31 16:44:18 2013 -0700
@@ -362,7 +362,7 @@
* default implementation of this method searches for classes in the
* following order:
*
- *
+ *
*
* Invoke {@link #findLoadedClass(String)} to check if the class
* has already been loaded.
@@ -488,7 +488,7 @@
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
if (ReflectUtil.isNonPublicProxyClass(cls)) {
- for (Class intf: cls.getInterfaces()) {
+ for (Class> intf: cls.getInterfaces()) {
checkPackageAccess(intf, pd);
}
return;
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/ClassValue.java
--- a/src/share/classes/java/lang/ClassValue.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/ClassValue.java Thu Oct 31 16:44:18 2013 -0700
@@ -692,7 +692,7 @@
/** Remove all stale entries, everywhere. */
private void removeStaleEntries() {
- Entry[] cache = getCache();
+ Entry>[] cache = getCache();
removeStaleEntries(cache, 0, cache.length + PROBE_LIMIT - 1);
}
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/Comparable.java
--- a/src/share/classes/java/lang/Comparable.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/Comparable.java Thu Oct 31 16:44:18 2013 -0700
@@ -93,7 +93,6 @@
* @see java.util.Comparator
* @since 1.2
*/
-@FunctionalInterface
public interface Comparable {
/**
* Compares this object with the specified object for order. Returns a
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/ConditionalSpecialCasing.java
--- a/src/share/classes/java/lang/ConditionalSpecialCasing.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/ConditionalSpecialCasing.java Thu Oct 31 16:44:18 2013 -0700
@@ -74,7 +74,6 @@
new Entry(0x00CC, new char[]{0x0069, 0x0307, 0x0300}, new char[]{0x00CC}, "lt", 0), // # LATIN CAPITAL LETTER I WITH GRAVE
new Entry(0x00CD, new char[]{0x0069, 0x0307, 0x0301}, new char[]{0x00CD}, "lt", 0), // # LATIN CAPITAL LETTER I WITH ACUTE
new Entry(0x0128, new char[]{0x0069, 0x0307, 0x0303}, new char[]{0x0128}, "lt", 0), // # LATIN CAPITAL LETTER I WITH TILDE
- new Entry(0x0130, new char[]{0x0069, 0x0307}, new char[]{0x0130}, "lt", 0), // # LATIN CAPITAL LETTER I WITH DOT ABOVE
//# ================================================================================
//# Turkish and Azeri
@@ -85,10 +84,7 @@
new Entry(0x0049, new char[]{0x0131}, new char[]{0x0049}, "tr", NOT_BEFORE_DOT), // # LATIN CAPITAL LETTER I
new Entry(0x0049, new char[]{0x0131}, new char[]{0x0049}, "az", NOT_BEFORE_DOT), // # LATIN CAPITAL LETTER I
new Entry(0x0069, new char[]{0x0069}, new char[]{0x0130}, "tr", 0), // # LATIN SMALL LETTER I
- new Entry(0x0069, new char[]{0x0069}, new char[]{0x0130}, "az", 0), // # LATIN SMALL LETTER I
- //# ================================================================================
- //# Other
- new Entry(0x0130, new char[]{0x0069, 0x0307}, new char[]{0x0130}, "en", 0), // # LATIN CAPITALLETTER I WITH DOT ABOVE
+ new Entry(0x0069, new char[]{0x0069}, new char[]{0x0130}, "az", 0) // # LATIN SMALL LETTER I
};
// A hash table that contains the above entries
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/Double.java
--- a/src/share/classes/java/lang/Double.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/Double.java Thu Oct 31 16:44:18 2013 -0700
@@ -361,15 +361,11 @@
* - SignedInteger
*
*
- *
- *
*
* - HexFloatingPointLiteral:
*
- HexSignificand BinaryExponent FloatTypeSuffixopt
*
*
- *
- *
*
* - HexSignificand:
*
- HexNumeral
@@ -380,15 +376,11 @@
* {@code .} HexDigits
*
*
- *
- *
*
* - BinaryExponent:
*
- BinaryExponentIndicator SignedInteger
*
*
- *
- *
*
* - BinaryExponentIndicator:
*
- {@code p}
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/Float.java
--- a/src/share/classes/java/lang/Float.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/Float.java Thu Oct 31 16:44:18 2013 -0700
@@ -321,15 +321,11 @@
*
- SignedInteger
*
*
- *
- *
*
* - HexFloatingPointLiteral:
*
- HexSignificand BinaryExponent FloatTypeSuffixopt
*
*
- *
- *
*
* - HexSignificand:
*
- HexNumeral
@@ -340,15 +336,11 @@
* {@code .} HexDigits
*
*
- *
- *
*
* - BinaryExponent:
*
- BinaryExponentIndicator SignedInteger
*
*
- *
- *
*
* - BinaryExponentIndicator:
*
- {@code p}
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/Integer.java
--- a/src/share/classes/java/lang/Integer.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/Integer.java Thu Oct 31 16:44:18 2013 -0700
@@ -1123,7 +1123,7 @@
*
- Signopt {@code 0X} HexDigits
*
- Signopt {@code #} HexDigits
*
- Signopt {@code 0} OctalDigits
- *
+ *
*
- Sign:
*
- {@code -}
*
- {@code +}
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/Iterable.java
--- a/src/share/classes/java/lang/Iterable.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/Iterable.java Thu Oct 31 16:44:18 2013 -0700
@@ -42,7 +42,6 @@
* @since 1.5
* @jls 14.14.2 The enhanced for statement
*/
-@FunctionalInterface
public interface Iterable {
/**
* Returns an iterator over elements of type {@code T}.
@@ -52,10 +51,12 @@
Iterator iterator();
/**
- * Performs the given action on the contents of the {@code Iterable}, in the
- * order elements occur when iterating, until all elements have been
- * processed or the action throws an exception. Errors or runtime
- * exceptions thrown by the action are relayed to the caller.
+ * Performs the given action for each element of the {@code Iterable}
+ * until all elements have been processed or the action throws an
+ * exception. Unless otherwise specified by the implementing class,
+ * actions are performed in the order of iteration (if an iteration order
+ * is specified). Exceptions thrown by the action are relayed to the
+ * caller.
*
* @implSpec
*
The default implementation behaves as if:
@@ -100,4 +101,3 @@
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
-
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/Long.java
--- a/src/share/classes/java/lang/Long.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/Long.java Thu Oct 31 16:44:18 2013 -0700
@@ -853,7 +853,7 @@
*
- Signopt {@code 0X} HexDigits
*
- Signopt {@code #} HexDigits
*
- Signopt {@code 0} OctalDigits
- *
+ *
*
- Sign:
*
- {@code -}
*
- {@code +}
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/Readable.java
--- a/src/share/classes/java/lang/Readable.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/Readable.java Thu Oct 31 16:44:18 2013 -0700
@@ -34,7 +34,6 @@
*
* @since 1.5
*/
-@FunctionalInterface
public interface Readable {
/**
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/RuntimePermission.java
--- a/src/share/classes/java/lang/RuntimePermission.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/RuntimePermission.java Thu Oct 31 16:44:18 2013 -0700
@@ -47,7 +47,6 @@
* The following table lists all the possible RuntimePermission target names,
* and for each provides a description of what the permission allows
* and a discussion of the risks of granting code the permission.
- *
*
*
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/SecurityManager.java
--- a/src/share/classes/java/lang/SecurityManager.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/SecurityManager.java Thu Oct 31 16:44:18 2013 -0700
@@ -56,7 +56,7 @@
* are called by various methods in the Java libraries before those
* methods perform certain potentially sensitive operations. The
* invocation of such a check
method typically looks like this:
- *
+ *
* SecurityManager security = System.getSecurityManager();
* if (security != null) {
* security.checkXXX(argument, . . . );
@@ -323,7 +323,7 @@
* by {@link ClassLoader#getSystemClassLoader}) or one of its ancestors.
*
* This method will return
- * null
in the following three cases:
+ * null
in the following three cases:
*
* - All methods on the execution stack are from classes
* defined using the system class loader or one of its ancestors.
@@ -370,7 +370,7 @@
* by {@link ClassLoader#getSystemClassLoader}) or one of its ancestors.
*
* This method will return
- * null
in the following three cases:
+ * null
in the following three cases:
*
* - All methods on the execution stack are from classes
* defined using the system class loader or one of its ancestors.
@@ -429,7 +429,7 @@
* by {@link ClassLoader#getSystemClassLoader}) or one of its ancestors.
*
* This method will return
- * -1 in the following three cases:
+ * -1 in the following three cases:
*
* - All methods on the execution stack are from classes
* defined using the system class loader or one of its ancestors.
@@ -1281,7 +1281,6 @@
* This method calls
checkPermission
with the
* PropertyPermission(key, "read")
permission.
*
- *
* If you override this method, then you should make a call to
* super.checkPropertyAccess
* at the point the overridden method would normally throw an
@@ -1714,7 +1713,7 @@
throw new NullPointerException("class can't be null");
}
if (which != Member.PUBLIC) {
- Class stack[] = getClassContext();
+ Class> stack[] = getClassContext();
/*
* stack depth of 4 should be the caller of one of the
* methods in java.lang.Class that invoke checkMember
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/Short.java
--- a/src/share/classes/java/lang/Short.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/Short.java Thu Oct 31 16:44:18 2013 -0700
@@ -249,7 +249,7 @@
*
- Signopt {@code 0X} HexDigits
*
- Signopt {@code #} HexDigits
*
- Signopt {@code 0} OctalDigits
- *
+ *
*
- Sign:
*
- {@code -}
*
- {@code +}
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/String.java
--- a/src/share/classes/java/lang/String.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/String.java Thu Oct 31 16:44:18 2013 -0700
@@ -47,16 +47,16 @@
* Strings are constant; their values cannot be changed after they
* are created. String buffers support mutable strings.
* Because String objects are immutable they can be shared. For example:
- *
+ *
* String str = "abc";
*
* is equivalent to:
- *
+ *
* char data[] = {'a', 'b', 'c'};
* String str = new String(data);
*
* Here are some more examples of how strings can be used:
- *
+ *
* System.out.println("abc");
* String cde = "cde";
* System.out.println("abc" + cde);
@@ -786,7 +786,7 @@
* {@code srcEnd-srcBegin}). The characters are copied into the
* subarray of {@code dst} starting at index {@code dstBegin}
* and ending at index:
- *
+ *
* dstbegin + (srcEnd-srcBegin) - 1
*
*
@@ -2598,21 +2598,14 @@
}
if (localeDependent || srcChar == '\u03A3') { // GREEK CAPITAL LETTER SIGMA
lowerChar = ConditionalSpecialCasing.toLowerCaseEx(this, i, locale);
- } else if (srcChar == '\u0130') { // LATIN CAPITAL LETTER I DOT
- lowerChar = Character.ERROR;
} else {
lowerChar = Character.toLowerCase(srcChar);
}
if ((lowerChar == Character.ERROR)
|| (lowerChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) {
if (lowerChar == Character.ERROR) {
- if (!localeDependent && srcChar == '\u0130') {
- lowerCharArray =
- ConditionalSpecialCasing.toLowerCaseCharArray(this, i, Locale.ENGLISH);
- } else {
- lowerCharArray =
- ConditionalSpecialCasing.toLowerCaseCharArray(this, i, locale);
- }
+ lowerCharArray =
+ ConditionalSpecialCasing.toLowerCaseCharArray(this, i, locale);
} else if (srcCount == 2) {
resultOffset += Character.toChars(lowerChar, result, i + resultOffset) - srcCount;
continue;
@@ -2669,7 +2662,7 @@
* {@code String} may be a different length than the original {@code String}.
*
* Examples of locale-sensitive and 1:M case mappings are in the following table.
- *
+ *
*
*
* Language Code of Locale |
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/System.java
--- a/src/share/classes/java/lang/System.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/System.java Thu Oct 31 16:44:18 2013 -0700
@@ -26,10 +26,12 @@
import java.io.*;
import java.lang.reflect.Executable;
+import java.lang.annotation.Annotation;
import java.security.AccessControlContext;
import java.util.Properties;
import java.util.PropertyPermission;
import java.util.StringTokenizer;
+import java.util.Map;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.AllPermission;
@@ -1227,6 +1229,9 @@
public AnnotationType getAnnotationType(Class> klass) {
return klass.getAnnotationType();
}
+ public Map, Annotation> getDeclaredAnnotationMap(Class> klass) {
+ return klass.getDeclaredAnnotationMap();
+ }
public byte[] getRawClassAnnotations(Class> klass) {
return klass.getRawAnnotations();
}
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/Thread.java
--- a/src/share/classes/java/lang/Thread.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/Thread.java Thu Oct 31 16:44:18 2013 -0700
@@ -76,7 +76,7 @@
* Thread
. An instance of the subclass can then be
* allocated and started. For example, a thread that computes primes
* larger than a stated value could be written as follows:
- *
+ *
* class PrimeThread extends Thread {
* long minPrime;
* PrimeThread(long minPrime) {
@@ -91,7 +91,7 @@
*
*
* The following code would then create a thread and start it running:
- *
+ *
* PrimeThread p = new PrimeThread(143);
* p.start();
*
@@ -102,7 +102,7 @@
* then be allocated, passed as an argument when creating
* Thread
, and started. The same example in this other
* style looks like the following:
- *
+ *
* class PrimeRun implements Runnable {
* long minPrime;
* PrimeRun(long minPrime) {
@@ -117,7 +117,7 @@
*
*
* The following code would then create a thread and start it running:
- *
+ *
* PrimeRun p = new PrimeRun(143);
* new Thread(p).start();
*
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java
--- a/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java Thu Oct 31 16:44:18 2013 -0700
@@ -101,7 +101,6 @@
* should implement.
* @param additionalBridges Method types for additional signatures to be
* bridged to the implementation method
- * @throws ReflectiveOperationException
* @throws LambdaConversionException If any of the meta-factory protocol
* invariants are violated
*/
@@ -114,7 +113,7 @@
boolean isSerializable,
Class>[] markerInterfaces,
MethodType[] additionalBridges)
- throws ReflectiveOperationException, LambdaConversionException {
+ throws LambdaConversionException {
this.targetClass = caller.lookupClass();
this.invokedType = invokedType;
@@ -160,7 +159,7 @@
* @throws ReflectiveOperationException
*/
abstract CallSite buildCallSite()
- throws ReflectiveOperationException, LambdaConversionException;
+ throws LambdaConversionException;
/**
* Check the meta-factory arguments for errors
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java
--- a/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java Thu Oct 31 16:44:18 2013 -0700
@@ -26,16 +26,19 @@
package java.lang.invoke;
import jdk.internal.org.objectweb.asm.*;
+import sun.invoke.util.BytecodeDescriptor;
import sun.misc.Unsafe;
import sun.security.action.GetPropertyAction;
import java.io.FilePermission;
+import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.security.AccessController;
import java.security.PrivilegedAction;
-import java.security.ProtectionDomain;
+import java.util.LinkedHashSet;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.PropertyPermission;
+import java.util.Set;
import static jdk.internal.org.objectweb.asm.Opcodes.*;
@@ -50,14 +53,19 @@
private static final int CLASSFILE_VERSION = 51;
private static final String METHOD_DESCRIPTOR_VOID = Type.getMethodDescriptor(Type.VOID_TYPE);
- private static final String NAME_MAGIC_ACCESSOR_IMPL = "java/lang/invoke/MagicLambdaImpl";
+ private static final String JAVA_LANG_OBJECT = "java/lang/Object";
private static final String NAME_CTOR = "";
+ private static final String NAME_FACTORY = "get$Lambda";
//Serialization support
private static final String NAME_SERIALIZED_LAMBDA = "java/lang/invoke/SerializedLambda";
+ private static final String NAME_NOT_SERIALIZABLE_EXCEPTION = "java/io/NotSerializableException";
private static final String DESCR_METHOD_WRITE_REPLACE = "()Ljava/lang/Object;";
+ private static final String DESCR_METHOD_WRITE_OBJECT = "(Ljava/io/ObjectOutputStream;)V";
+ private static final String DESCR_METHOD_READ_OBJECT = "(Ljava/io/ObjectInputStream;)V";
private static final String NAME_METHOD_WRITE_REPLACE = "writeReplace";
- private static final String NAME_OBJECT = "java/lang/Object";
+ private static final String NAME_METHOD_READ_OBJECT = "readObject";
+ private static final String NAME_METHOD_WRITE_OBJECT = "writeObject";
private static final String DESCR_CTOR_SERIALIZED_LAMBDA
= MethodType.methodType(void.class,
Class.class,
@@ -65,6 +73,12 @@
int.class, String.class, String.class, String.class,
String.class,
Object[].class).toMethodDescriptorString();
+ private static final String DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION
+ = MethodType.methodType(void.class, String.class).toMethodDescriptorString();
+ private static final String[] SER_HOSTILE_EXCEPTIONS = new String[] {NAME_NOT_SERIALIZABLE_EXCEPTION};
+
+
+ private static final String[] EMPTY_STRING_ARRAY = new String[0];
// Used to ensure that each spun class name is unique
private static final AtomicInteger counter = new AtomicInteger(0);
@@ -84,15 +98,12 @@
private final String implMethodClassName; // Name of type containing implementation "CC"
private final String implMethodName; // Name of implementation method "impl"
private final String implMethodDesc; // Type descriptor for implementation methods "(I)Ljava/lang/String;"
- private final Type[] implMethodArgumentTypes; // ASM types for implementation method parameters
- private final Type implMethodReturnType; // ASM type for implementation method return type "Ljava/lang/String;"
+ private final Class> implMethodReturnClass; // class for implementaion method return type "Ljava/lang/String;"
private final MethodType constructorType; // Generated class constructor type "(CC)void"
- private final String constructorDesc; // Type descriptor for constructor "(LCC;)V"
private final ClassWriter cw; // ASM class writer
- private final Type[] argTypes; // ASM types for the constructor arguments
private final String[] argNames; // Generated names for the constructor arguments
+ private final String[] argDescs; // Type descriptors for the constructor arguments
private final String lambdaClassName; // Generated name for the generated class "X$$Lambda$1"
- private final Type[] instantiatedArgumentTypes; // ASM types for the functional interface arguments
/**
* General meta-factory constructor, supporting both standard cases and
@@ -128,7 +139,6 @@
* should implement.
* @param additionalBridges Method types for additional signatures to be
* bridged to the implementation method
- * @throws ReflectiveOperationException
* @throws LambdaConversionException If any of the meta-factory protocol
* invariants are violated
*/
@@ -141,29 +151,30 @@
boolean isSerializable,
Class>[] markerInterfaces,
MethodType[] additionalBridges)
- throws ReflectiveOperationException, LambdaConversionException {
+ throws LambdaConversionException {
super(caller, invokedType, samMethodName, samMethodType,
implMethod, instantiatedMethodType,
isSerializable, markerInterfaces, additionalBridges);
implMethodClassName = implDefiningClass.getName().replace('.', '/');
implMethodName = implInfo.getName();
implMethodDesc = implMethodType.toMethodDescriptorString();
- Type implMethodAsmType = Type.getMethodType(implMethodDesc);
- implMethodArgumentTypes = implMethodAsmType.getArgumentTypes();
- implMethodReturnType = (implKind == MethodHandleInfo.REF_newInvokeSpecial)
- ? Type.getObjectType(implMethodClassName)
- : implMethodAsmType.getReturnType();
+ implMethodReturnClass = (implKind == MethodHandleInfo.REF_newInvokeSpecial)
+ ? implDefiningClass
+ : implMethodType.returnType();
constructorType = invokedType.changeReturnType(Void.TYPE);
- constructorDesc = constructorType.toMethodDescriptorString();
lambdaClassName = targetClass.getName().replace('.', '/') + "$$Lambda$" + counter.incrementAndGet();
cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
- argTypes = Type.getArgumentTypes(constructorDesc);
- argNames = new String[argTypes.length];
- for (int i = 0; i < argTypes.length; i++) {
- argNames[i] = "arg$" + (i + 1);
+ int parameterCount = invokedType.parameterCount();
+ if (parameterCount > 0) {
+ argNames = new String[parameterCount];
+ argDescs = new String[parameterCount];
+ for (int i = 0; i < parameterCount; i++) {
+ argNames[i] = "arg$" + (i + 1);
+ argDescs[i] = BytecodeDescriptor.unparse(invokedType.parameterType(i));
+ }
+ } else {
+ argNames = argDescs = EMPTY_STRING_ARRAY;
}
- instantiatedArgumentTypes = Type.getArgumentTypes(
- instantiatedMethodType.toMethodDescriptorString());
}
/**
@@ -179,36 +190,44 @@
* is not found
*/
@Override
- CallSite buildCallSite() throws ReflectiveOperationException, LambdaConversionException {
+ CallSite buildCallSite() throws LambdaConversionException {
final Class> innerClass = spinInnerClass();
if (invokedType.parameterCount() == 0) {
final Constructor[] ctrs = AccessController.doPrivileged(
new PrivilegedAction() {
@Override
public Constructor[] run() {
- return innerClass.getDeclaredConstructors();
+ Constructor>[] ctrs = innerClass.getDeclaredConstructors();
+ if (ctrs.length == 1) {
+ // The lambda implementing inner class constructor is private, set
+ // it accessible (by us) before creating the constant sole instance
+ ctrs[0].setAccessible(true);
+ }
+ return ctrs;
}
- });
+ });
if (ctrs.length != 1) {
- throw new ReflectiveOperationException("Expected one lambda constructor for "
+ throw new LambdaConversionException("Expected one lambda constructor for "
+ innerClass.getCanonicalName() + ", got " + ctrs.length);
}
- // The lambda implementing inner class constructor is private, set
- // it accessible (by us) before creating the constant sole instance
- AccessController.doPrivileged(new PrivilegedAction() {
- @Override
- public Void run() {
- ctrs[0].setAccessible(true);
- return null;
- }
- });
- Object inst = ctrs[0].newInstance();
- return new ConstantCallSite(MethodHandles.constant(samBase, inst));
+
+ try {
+ Object inst = ctrs[0].newInstance();
+ return new ConstantCallSite(MethodHandles.constant(samBase, inst));
+ }
+ catch (ReflectiveOperationException e) {
+ throw new LambdaConversionException("Exception instantiating lambda object", e);
+ }
} else {
- return new ConstantCallSite(
- MethodHandles.Lookup.IMPL_LOOKUP
- .findConstructor(innerClass, constructorType)
- .asType(constructorType.changeReturnType(samBase)));
+ try {
+ UNSAFE.ensureClassInitialized(innerClass);
+ return new ConstantCallSite(
+ MethodHandles.Lookup.IMPL_LOOKUP
+ .findStatic(innerClass, NAME_FACTORY, invokedType));
+ }
+ catch (ReflectiveOperationException e) {
+ throw new LambdaConversionException("Exception finding constructor", e);
+ }
}
}
@@ -228,44 +247,59 @@
* is not found
*/
private Class> spinInnerClass() throws LambdaConversionException {
- String[] interfaces = new String[markerInterfaces.length + 1];
- interfaces[0] = samBase.getName().replace('.', '/');
- for (int i=0; i itfs = new LinkedHashSet<>(markerInterfaces.length + 1);
+ itfs.add(samIntf);
+ for (Class> markerInterface : markerInterfaces) {
+ itfs.add(markerInterface.getName().replace('.', '/'));
+ accidentallySerializable |= !isSerializable && Serializable.class.isAssignableFrom(markerInterface);
+ }
+ interfaces = itfs.toArray(new String[itfs.size()]);
}
+
cw.visit(CLASSFILE_VERSION, ACC_SUPER + ACC_FINAL + ACC_SYNTHETIC,
lambdaClassName, null,
- NAME_MAGIC_ACCESSOR_IMPL, interfaces);
+ JAVA_LANG_OBJECT, interfaces);
// Generate final fields to be filled in by constructor
- for (int i = 0; i < argTypes.length; i++) {
+ for (int i = 0; i < argDescs.length; i++) {
FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_FINAL,
argNames[i],
- argTypes[i].getDescriptor(),
+ argDescs[i],
null, null);
fv.visitEnd();
}
generateConstructor();
+ if (invokedType.parameterCount() != 0) {
+ generateFactory();
+ }
+
// Forward the SAM method
- String methodDescriptor = samMethodType.toMethodDescriptorString();
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, samMethodName,
- methodDescriptor, null, null);
- new ForwardingMethodGenerator(mv).generate(methodDescriptor);
+ samMethodType.toMethodDescriptorString(), null, null);
+ new ForwardingMethodGenerator(mv).generate(samMethodType);
// Forward the bridges
if (additionalBridges != null) {
for (MethodType mt : additionalBridges) {
- methodDescriptor = mt.toMethodDescriptorString();
mv = cw.visitMethod(ACC_PUBLIC|ACC_BRIDGE, samMethodName,
- methodDescriptor, null, null);
- new ForwardingMethodGenerator(mv).generate(methodDescriptor);
+ mt.toMethodDescriptorString(), null, null);
+ new ForwardingMethodGenerator(mv).generate(mt);
}
}
if (isSerializable)
- generateWriteReplace();
+ generateSerializationFriendlyMethods();
+ else if (accidentallySerializable)
+ generateSerializationHostileMethods();
cw.visitEnd();
@@ -287,21 +321,27 @@
new PropertyPermission("user.dir", "read"));
}
- ClassLoader loader = targetClass.getClassLoader();
- ProtectionDomain pd = (loader == null)
- ? null
- : AccessController.doPrivileged(
- new PrivilegedAction() {
- @Override
- public ProtectionDomain run() {
- return targetClass.getProtectionDomain();
- }
- }
- );
+ return UNSAFE.defineAnonymousClass(targetClass, classBytes, null);
+ }
- return UNSAFE.defineClass(lambdaClassName,
- classBytes, 0, classBytes.length,
- loader, pd);
+ /**
+ * Generate the factory method for the class
+ */
+ private void generateFactory() {
+ MethodVisitor m = cw.visitMethod(ACC_PRIVATE | ACC_STATIC, NAME_FACTORY, invokedType.toMethodDescriptorString(), null, null);
+ m.visitCode();
+ m.visitTypeInsn(NEW, lambdaClassName);
+ m.visitInsn(Opcodes.DUP);
+ int parameterCount = invokedType.parameterCount();
+ for (int typeIndex = 0, varIndex = 0; typeIndex < parameterCount; typeIndex++) {
+ Class> argType = invokedType.parameterType(typeIndex);
+ m.visitVarInsn(getLoadOpcode(argType), varIndex);
+ varIndex += getParameterSize(argType);
+ }
+ m.visitMethodInsn(INVOKESPECIAL, lambdaClassName, NAME_CTOR, constructorType.toMethodDescriptorString());
+ m.visitInsn(ARETURN);
+ m.visitMaxs(-1, -1);
+ m.visitEnd();
}
/**
@@ -310,18 +350,18 @@
private void generateConstructor() {
// Generate constructor
MethodVisitor ctor = cw.visitMethod(ACC_PRIVATE, NAME_CTOR,
- constructorDesc, null, null);
+ constructorType.toMethodDescriptorString(), null, null);
ctor.visitCode();
ctor.visitVarInsn(ALOAD, 0);
- ctor.visitMethodInsn(INVOKESPECIAL, NAME_MAGIC_ACCESSOR_IMPL, NAME_CTOR,
+ ctor.visitMethodInsn(INVOKESPECIAL, JAVA_LANG_OBJECT, NAME_CTOR,
METHOD_DESCRIPTOR_VOID);
- int lvIndex = 0;
- for (int i = 0; i < argTypes.length; i++) {
+ int parameterCount = invokedType.parameterCount();
+ for (int i = 0, lvIndex = 0; i < parameterCount; i++) {
ctor.visitVarInsn(ALOAD, 0);
- ctor.visitVarInsn(argTypes[i].getOpcode(ILOAD), lvIndex + 1);
- lvIndex += argTypes[i].getSize();
- ctor.visitFieldInsn(PUTFIELD, lambdaClassName, argNames[i],
- argTypes[i].getDescriptor());
+ Class> argType = invokedType.parameterType(i);
+ ctor.visitVarInsn(getLoadOpcode(argType), lvIndex + 1);
+ lvIndex += getParameterSize(argType);
+ ctor.visitFieldInsn(PUTFIELD, lambdaClassName, argNames[i], argDescs[i]);
}
ctor.visitInsn(RETURN);
// Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored
@@ -330,9 +370,9 @@
}
/**
- * Generate the writeReplace method (if needed for serialization)
+ * Generate a writeReplace method that supports serialization
*/
- private void generateWriteReplace() {
+ private void generateSerializationFriendlyMethods() {
TypeConvertingMethodAdapter mv
= new TypeConvertingMethodAdapter(
cw.visitMethod(ACC_PRIVATE + ACC_FINAL,
@@ -351,16 +391,14 @@
mv.visitLdcInsn(implInfo.getName());
mv.visitLdcInsn(implInfo.getMethodType().toMethodDescriptorString());
mv.visitLdcInsn(instantiatedMethodType.toMethodDescriptorString());
-
- mv.iconst(argTypes.length);
- mv.visitTypeInsn(ANEWARRAY, NAME_OBJECT);
- for (int i = 0; i < argTypes.length; i++) {
+ mv.iconst(argDescs.length);
+ mv.visitTypeInsn(ANEWARRAY, JAVA_LANG_OBJECT);
+ for (int i = 0; i < argDescs.length; i++) {
mv.visitInsn(DUP);
mv.iconst(i);
mv.visitVarInsn(ALOAD, 0);
- mv.visitFieldInsn(GETFIELD, lambdaClassName, argNames[i],
- argTypes[i].getDescriptor());
- mv.boxIfTypePrimitive(argTypes[i]);
+ mv.visitFieldInsn(GETFIELD, lambdaClassName, argNames[i], argDescs[i]);
+ mv.boxIfTypePrimitive(Type.getType(argDescs[i]));
mv.visitInsn(AASTORE);
}
mv.visitMethodInsn(INVOKESPECIAL, NAME_SERIALIZED_LAMBDA, NAME_CTOR,
@@ -372,6 +410,37 @@
}
/**
+ * Generate a readObject/writeObject method that is hostile to serialization
+ */
+ private void generateSerializationHostileMethods() {
+ MethodVisitor mv = cw.visitMethod(ACC_PRIVATE + ACC_FINAL,
+ NAME_METHOD_WRITE_OBJECT, DESCR_METHOD_WRITE_OBJECT,
+ null, SER_HOSTILE_EXCEPTIONS);
+ mv.visitCode();
+ mv.visitTypeInsn(NEW, NAME_NOT_SERIALIZABLE_EXCEPTION);
+ mv.visitInsn(DUP);
+ mv.visitLdcInsn("Non-serializable lambda");
+ mv.visitMethodInsn(INVOKESPECIAL, NAME_NOT_SERIALIZABLE_EXCEPTION, NAME_CTOR,
+ DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION);
+ mv.visitInsn(ATHROW);
+ mv.visitMaxs(-1, -1);
+ mv.visitEnd();
+
+ mv = cw.visitMethod(ACC_PRIVATE + ACC_FINAL,
+ NAME_METHOD_READ_OBJECT, DESCR_METHOD_READ_OBJECT,
+ null, SER_HOSTILE_EXCEPTIONS);
+ mv.visitCode();
+ mv.visitTypeInsn(NEW, NAME_NOT_SERIALIZABLE_EXCEPTION);
+ mv.visitInsn(DUP);
+ mv.visitLdcInsn("Non-serializable lambda");
+ mv.visitMethodInsn(INVOKESPECIAL, NAME_NOT_SERIALIZABLE_EXCEPTION, NAME_CTOR,
+ DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION);
+ mv.visitInsn(ATHROW);
+ mv.visitMaxs(-1, -1);
+ mv.visitEnd();
+ }
+
+ /**
* This class generates a method body which calls the lambda implementation
* method, converting arguments, as needed.
*/
@@ -381,20 +450,19 @@
super(mv);
}
- void generate(String methodDescriptor) {
+ void generate(MethodType methodType) {
visitCode();
if (implKind == MethodHandleInfo.REF_newInvokeSpecial) {
visitTypeInsn(NEW, implMethodClassName);
visitInsn(DUP);
}
- for (int i = 0; i < argTypes.length; i++) {
+ for (int i = 0; i < argNames.length; i++) {
visitVarInsn(ALOAD, 0);
- visitFieldInsn(GETFIELD, lambdaClassName, argNames[i],
- argTypes[i].getDescriptor());
+ visitFieldInsn(GETFIELD, lambdaClassName, argNames[i], argDescs[i]);
}
- convertArgumentTypes(Type.getArgumentTypes(methodDescriptor));
+ convertArgumentTypes(methodType);
// Invoke the method we want to forward to
visitMethodInsn(invocationOpcode(), implMethodClassName, implMethodName, implMethodDesc);
@@ -402,46 +470,36 @@
// Convert the return value (if any) and return it
// Note: if adapting from non-void to void, the 'return'
// instruction will pop the unneeded result
- Type samReturnType = Type.getReturnType(methodDescriptor);
- convertType(implMethodReturnType, samReturnType, samReturnType);
- visitInsn(samReturnType.getOpcode(Opcodes.IRETURN));
+ Class> samReturnClass = methodType.returnType();
+ convertType(implMethodReturnClass, samReturnClass, samReturnClass);
+ visitInsn(getReturnOpcode(samReturnClass));
// Maxs computed by ClassWriter.COMPUTE_MAXS,these arguments ignored
visitMaxs(-1, -1);
visitEnd();
}
- private void convertArgumentTypes(Type[] samArgumentTypes) {
+ private void convertArgumentTypes(MethodType samType) {
int lvIndex = 0;
boolean samIncludesReceiver = implIsInstanceMethod &&
- argTypes.length == 0;
+ invokedType.parameterCount() == 0;
int samReceiverLength = samIncludesReceiver ? 1 : 0;
if (samIncludesReceiver) {
// push receiver
- Type rcvrType = samArgumentTypes[0];
- Type instantiatedRcvrType = instantiatedArgumentTypes[0];
-
- visitVarInsn(rcvrType.getOpcode(ILOAD), lvIndex + 1);
- lvIndex += rcvrType.getSize();
- convertType(rcvrType, Type.getType(implDefiningClass), instantiatedRcvrType);
+ Class> rcvrType = samType.parameterType(0);
+ visitVarInsn(getLoadOpcode(rcvrType), lvIndex + 1);
+ lvIndex += getParameterSize(rcvrType);
+ convertType(rcvrType, implDefiningClass, instantiatedMethodType.parameterType(0));
}
- int argOffset = implMethodArgumentTypes.length - samArgumentTypes.length;
- for (int i = samReceiverLength; i < samArgumentTypes.length; i++) {
- Type argType = samArgumentTypes[i];
- Type targetType = implMethodArgumentTypes[argOffset + i];
- Type instantiatedArgType = instantiatedArgumentTypes[i];
-
- visitVarInsn(argType.getOpcode(ILOAD), lvIndex + 1);
- lvIndex += argType.getSize();
- convertType(argType, targetType, instantiatedArgType);
+ int samParametersLength = samType.parameterCount();
+ int argOffset = implMethodType.parameterCount() - samParametersLength;
+ for (int i = samReceiverLength; i < samParametersLength; i++) {
+ Class> argType = samType.parameterType(i);
+ visitVarInsn(getLoadOpcode(argType), lvIndex + 1);
+ lvIndex += getParameterSize(argType);
+ convertType(argType, implMethodType.parameterType(argOffset + i), instantiatedMethodType.parameterType(i));
}
}
- private void convertType(Type argType, Type targetType, Type functionalType) {
- convertType(argType.getDescriptor(),
- targetType.getDescriptor(),
- functionalType.getDescriptor());
- }
-
private int invocationOpcode() throws InternalError {
switch (implKind) {
case MethodHandleInfo.REF_invokeStatic:
@@ -459,4 +517,43 @@
}
}
}
+
+ static int getParameterSize(Class> c) {
+ if (c == Void.TYPE) {
+ return 0;
+ } else if (c == Long.TYPE || c == Double.TYPE) {
+ return 2;
+ }
+ return 1;
+ }
+
+ static int getLoadOpcode(Class> c) {
+ if(c == Void.TYPE) {
+ throw new InternalError("Unexpected void type of load opcode");
+ }
+ return ILOAD + getOpcodeOffset(c);
+ }
+
+ static int getReturnOpcode(Class> c) {
+ if(c == Void.TYPE) {
+ return RETURN;
+ }
+ return IRETURN + getOpcodeOffset(c);
+ }
+
+ private static int getOpcodeOffset(Class> c) {
+ if (c.isPrimitive()) {
+ if (c == Long.TYPE) {
+ return 1;
+ } else if (c == Float.TYPE) {
+ return 2;
+ } else if (c == Double.TYPE) {
+ return 3;
+ }
+ return 0;
+ } else {
+ return 4;
+ }
+ }
+
}
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/invoke/LambdaMetafactory.java
--- a/src/share/classes/java/lang/invoke/LambdaMetafactory.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/invoke/LambdaMetafactory.java Thu Oct 31 16:44:18 2013 -0700
@@ -29,88 +29,128 @@
import java.util.Arrays;
/**
- * Bootstrap methods for converting lambda expressions and method references to functional interface objects.
- *
- * For every lambda expressions or method reference in the source code, there is a target type which is a
- * functional interface. Evaluating a lambda expression produces an object of its target type. The mechanism for
- * evaluating lambda expressions is to invoke an invokedynamic call site, which takes arguments describing the sole
- * method of the functional interface and the implementation method, and returns an object (the lambda object) that
- * implements the target type. Methods of the lambda object invoke the implementation method. For method
- * references, the implementation method is simply the referenced method; for lambda expressions, the
- * implementation method is produced by the compiler based on the body of the lambda expression. The methods in
- * this file are the bootstrap methods for those invokedynamic call sites, called lambda factories, and the
- * bootstrap methods responsible for linking the lambda factories are called lambda meta-factories.
- *
- *
The bootstrap methods in this class take the information about the functional interface, the implementation
- * method, and the static types of the captured lambda arguments, and link a call site which, when invoked,
- * produces the lambda object.
- *
- *
When parameterized types are used, the instantiated type of the functional interface method may be different
- * from that in the functional interface. For example, consider
- * {@code interface I { int m(T x); }} if this functional interface type is used in a lambda
- * {@code I; v = ...}, we need both the actual functional interface method which has the signature
- * {@code (Object)int} and the erased instantiated type of the functional interface method (or simply
- * instantiated method type), which has signature
- * {@code (Byte)int}.
+ * Methods to facilitate the creation of simple "function objects" that
+ * implement one or more interfaces by delegation to a provided {@link MethodHandle},
+ * possibly after type adaptation and partial evaluation of arguments. These
+ * methods are typically used as bootstrap methods for {@code invokedynamic}
+ * call sites, to support the lambda expression and method
+ * reference expression features of the Java Programming Language.
*
- *
The argument list of the implementation method and the argument list of the functional interface method(s)
- * may differ in several ways. The implementation methods may have additional arguments to accommodate arguments
- * captured by the lambda expression; there may also be differences resulting from permitted adaptations of
- * arguments, such as casting, boxing, unboxing, and primitive widening. They may also differ because of var-args,
- * but this is expected to be handled by the compiler.
- *
- *
Invokedynamic call sites have two argument lists: a static argument list and a dynamic argument list. The
- * static argument list lives in the constant pool; the dynamic argument list lives on the operand stack at
- * invocation time. The bootstrap method has access to the entire static argument list (which in this case,
- * contains method handles describing the implementation method and the canonical functional interface method),
- * as well as a method signature describing the number and static types (but not the values) of the dynamic
- * arguments, and the static return type of the invokedynamic site.
+ *
Indirect access to the behavior specified by the provided {@code MethodHandle}
+ * proceeds in order through three phases:
+ *
+ * - Linkage occurs when the methods in this class are invoked.
+ * They take as arguments an interface to be implemented (typically a
+ * functional interface, one with a single abstract method), a
+ * name and signature of a method from that interface to be implemented, a
+ * method handle describing the desired implementation behavior
+ * for that method, and possibly other additional metadata, and produce a
+ * {@link CallSite} whose target can be used to create suitable function
+ * objects. Linkage may involve dynamically loading a new class that
+ * implements the target interface. The {@code CallSite} can be considered a
+ * "factory" for function objects and so these linkage methods are referred
+ * to as "metafactories".
*
- * The implementation method is described with a method handle. In theory, any method handle could be used.
- * Currently supported are method handles representing invocation of virtual, interface, constructor and static
- * methods.
+ *
- Capture occurs when the {@code CallSite}'s target is
+ * invoked, typically through an {@code invokedynamic} call site,
+ * producing a function object. This may occur many times for
+ * a single factory {@code CallSite}. Capture may involve allocation of a
+ * new function object, or may return an existing function object. The
+ * behavior {@code MethodHandle} may have additional parameters beyond those
+ * of the specified interface method; these are referred to as captured
+ * parameters, which must be provided as arguments to the
+ * {@code CallSite} target, and which may be early-bound to the behavior
+ * {@code MethodHandle}. The number of captured parameters and their types
+ * are determined during linkage.
*
- * Assume:
- *
- * - the functional interface method has N arguments, of types (U1, U2, ... Un) and return type Ru
- * - then the instantiated method type also has N arguments, of types (T1, T2, ... Tn) and return type Rt
- * - the implementation method has M arguments, of types (A1..Am) and return type Ra,
- * - the dynamic argument list has K arguments of types (D1..Dk), and the invokedynamic return site has
- * type Rd
- * - the functional interface type is F
+ * - Invocation occurs when an implemented interface method
+ * is invoked on a function object. This may occur many times for a single
+ * function object. The method referenced by the behavior {@code MethodHandle}
+ * is invoked with the captured arguments and any additional arguments
+ * provided on invocation, as if by {@link MethodHandle#invoke(Object...)}.
*
*
- * The following signature invariants must hold:
+ *
It is sometimes useful to restrict the set of inputs or results permitted
+ * at invocation. For example, when the generic interface {@code Predicate}
+ * is parameterized as {@code Predicate}, the input must be a
+ * {@code String}, even though the method to implement allows any {@code Object}.
+ * At linkage time, an additional {@link MethodType} parameter describes the
+ * "instantiated" method type; on invocation, the arguments and eventual result
+ * are checked against this {@code MethodType}.
+ *
+ * This class provides two forms of linkage methods: a standard version
+ * ({@link #metafactory(MethodHandles.Lookup, String, MethodType, MethodType, MethodHandle, MethodType)})
+ * using an optimized protocol, and an alternate version
+ * {@link #altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)}).
+ * The alternate version is a generalization of the standard version, providing
+ * additional control over the behavior of the generated function objects via
+ * flags and additional arguments. The alternate version adds the ability to
+ * manage the following attributes of function objects:
+ *
*
- * - Rd is a subtype of F
- * - For i=1..N, Ti is a subtype of Ui
- * - Either Rt and Ru are primitive and are the same type, or both are reference types and
- * Rt is a subtype of Ru
- * - If the implementation method is a static method:
- *
- * - K + N = M
- * - For i=1..K, Di = Ai
- * - For i=1..N, Ti is adaptable to Aj, where j=i+k
- *
- * - If the implementation method is an instance method:
- *
- * - K + N = M + 1
- * - D1 must be a subtype of the enclosing class for the implementation method
- * - For i=2..K, Di = Aj, where j=i-1
- * - For i=1..N, Ti is adaptable to Aj, where j=i+k-1
- *
- * - The return type Rt is void, or the return type Ra is not void and is adaptable to Rt
+ * - Bridging. It is sometimes useful to implement multiple
+ * variations of the method signature, involving argument or return type
+ * adaptation. This occurs when multiple distinct VM signatures for a method
+ * are logically considered to be the same method by the language. The
+ * flag {@code FLAG_BRIDGES} indicates that a list of additional
+ * {@code MethodType}s will be provided, each of which will be implemented
+ * by the resulting function object. These methods will share the same
+ * name and instantiated type.
+ *
+ * - Multiple interfaces. If needed, more than one interface
+ * can be implemented by the function object. (These additional interfaces
+ * are typically marker interfaces with no methods.) The flag {@code FLAG_MARKERS}
+ * indicates that a list of additional interfaces will be provided, each of
+ * which should be implemented by the resulting function object.
+ *
+ * - Serializability. The generated function objects do not
+ * generally support serialization. If desired, {@code FLAG_SERIALIZABLE}
+ * can be used to indicate that the function objects should be serializable.
+ * Serializable function objects will use, as their serialized form,
+ * instances of the class {@code SerializedLambda}, which requires additional
+ * assistance from the capturing class (the class described by the
+ * {@link MethodHandles.Lookup} parameter {@code caller}); see
+ * {@link SerializedLambda} for details.
*
*
- * Note that the potentially parameterized implementation return type provides the value for the SAM. Whereas
- * the completely known instantiated return type is adapted to the implementation arguments. Because the
- * instantiated type of the implementation method is not available, the adaptability of return types cannot be
- * checked as precisely at link-time as the arguments can be checked. Thus a loose version of link-time checking is
- * done on return type, while a strict version is applied to arguments.
+ *
Assume the linkage arguments are as follows:
+ *
+ * - {@code invokedType} (describing the {@code CallSite} signature) has
+ * K parameters of types (D1..Dk) and return type Rd;
+ * - {@code samMethodType} (describing the implemented method type) has N
+ * parameters, of types (U1..Un) and return type Ru;
+ * - {@code implMethod} (the {@code MethodHandle} providing the
+ * implementation has M parameters, of types (A1..Am) and return type Ra
+ * (if the method describes an instance method, the method type of this
+ * method handle already includes an extra first argument corresponding to
+ * the receiver);
+ * - {@code instantiatedMethodType} (allowing restrictions on invocation)
+ * has N parameters, of types (T1..Tn) and return type Rt.
+ *
+ *
+ * Then the following linkage invariants must hold:
+ *
+ * - Rd is an interface
+ * - {@code implMethod} is a direct method handle
+ * - {@code samMethodType} and {@code instantiatedMethodType} have the same
+ * arity N, and for i=1..N, Ti and Ui are the same type, or Ti and Ui are
+ * both reference types and Ti is a subtype of Ui
+ * - Either Rt and Ru are the same type, or both are reference types and
+ * Rt is a subtype of Ru
+ * - K + N = M
+ * - For i=1..K, Di = Ai
+ * - For i=1..N, Ti is adaptable to Aj, where j=i+k
+ * - The return type Rt is void, or the return type Ra is not void and is
+ * adaptable to Rt
+ *
+ *
+ * Further, at capture time, if {@code implMethod} corresponds to an instance
+ * method, and there are any capture arguments ({@code K > 0}), then the first
+ * capture argument (corresponding to the receiver) must be non-null.
*
*
A type Q is considered adaptable to S as follows:
*
- * Q | S | Link-time checks | Capture-time checks |
+ * Q | S | Link-time checks | Invocation-time checks |
*
* Primitive | Primitive |
* Q can be converted to S via a primitive widening conversion |
@@ -123,27 +163,59 @@
*
*
* Reference | Primitive |
- * strict: Q is a primitive wrapper and Primitive(Q) can be widened to S
- * loose: If Q is a primitive wrapper, check that Primitive(Q) can be widened to S |
- * If Q is not a primitive wrapper, cast Q to the base Wrapper(S); for example Number for numeric types |
+ * for parameter types: Q is a primitive wrapper and Primitive(Q)
+ * can be widened to S
+ * for return types: If Q is a primitive wrapper, check that
+ * Primitive(Q) can be widened to S |
+ * If Q is not a primitive wrapper, cast Q to the base Wrapper(S);
+ * for example Number for numeric types |
*
*
* Reference | Reference |
- * strict: S is a supertype of Q
- * loose: none |
+ * for parameter types: S is a supertype of Q
+ * for return types: none |
* Cast from Q to S |
*
*
*
- * The default bootstrap ({@link #metafactory}) represents the common cases and uses an optimized protocol.
- * Alternate bootstraps (e.g., {@link #altMetafactory}) exist to support uncommon cases such as serialization
- * or additional marker superinterfaces.
+ * @apiNote These linkage methods are designed to support the evaluation
+ * of lambda expressions and method references in the Java
+ * Language. For every lambda expressions or method reference in the source code,
+ * there is a target type which is a functional interface. Evaluating a lambda
+ * expression produces an object of its target type. The recommended mechanism
+ * for evaluating lambda expressions is to desugar the lambda body to a method,
+ * invoke an invokedynamic call site whose static argument list describes the
+ * sole method of the functional interface and the desugared implementation
+ * method, and returns an object (the lambda object) that implements the target
+ * type. (For method references, the implementation method is simply the
+ * referenced method; no desugaring is needed.)
*
+ * The argument list of the implementation method and the argument list of
+ * the interface method(s) may differ in several ways. The implementation
+ * methods may have additional arguments to accommodate arguments captured by
+ * the lambda expression; there may also be differences resulting from permitted
+ * adaptations of arguments, such as casting, boxing, unboxing, and primitive
+ * widening. (Varargs adaptations are not handled by the metafactories; these are
+ * expected to be handled by the caller.)
+ *
+ *
Invokedynamic call sites have two argument lists: a static argument list
+ * and a dynamic argument list. The static argument list is stored in the
+ * constant pool; the dynamic argument is pushed on the operand stack at capture
+ * time. The bootstrap method has access to the entire static argument list
+ * (which in this case, includes information describing the implementation method,
+ * the target interface, and the target interface method(s)), as well as a
+ * method signature describing the number and static types (but not the values)
+ * of the dynamic arguments and the static return type of the invokedynamic site.
+ *
+ * @implNote The implementation method is described with a method handle. In
+ * theory, any method handle could be used. Currently supported are direct method
+ * handles representing invocation of virtual, interface, constructor and static
+ * methods.
*/
public class LambdaMetafactory {
- /** Flag for alternate metafactories indicating the lambda object is
- * must to be serializable */
+ /** Flag for alternate metafactories indicating the lambda object
+ * must be serializable */
public static final int FLAG_SERIALIZABLE = 1 << 0;
/**
@@ -163,41 +235,58 @@
private static final MethodType[] EMPTY_MT_ARRAY = new MethodType[0];
/**
- * Standard meta-factory for conversion of lambda expressions or method
- * references to functional interfaces.
+ * Facilitates the creation of simple "function objects" that implement one
+ * or more interfaces by delegation to a provided {@link MethodHandle},
+ * after appropriate type adaptation and partial evaluation of arguments.
+ * Typically used as a bootstrap method for {@code invokedynamic}
+ * call sites, to support the lambda expression and method
+ * reference expression features of the Java Programming Language.
+ *
+ *
This is the standard, streamlined metafactory; additional flexibility
+ * is provided by {@link #altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)}.
+ * A general description of the behavior of this method is provided
+ * {@link LambdaMetafactory above}.
*
- * @param caller Stacked automatically by VM; represents a lookup context
- * with the accessibility privileges of the caller.
- * @param invokedName Stacked automatically by VM; the name of the invoked
- * method as it appears at the call site.
- * Used as the name of the functional interface method
- * to which the lambda or method reference is being
- * converted.
- * @param invokedType Stacked automatically by VM; the signature of the
- * invoked method, which includes the expected static
- * type of the returned lambda object, and the static
- * types of the captured arguments for the lambda.
+ *
When the target of the {@code CallSite} returned from this method is
+ * invoked, the resulting function objects are instances of a class which
+ * implements the interface named by the return type of {@code invokedType},
+ * declares a method with the name given by {@code invokedName} and the
+ * signature given by {@code samMethodType}. It may also override additional
+ * methods from {@code Object}.
+ *
+ * @param caller Represents a lookup context with the accessibility
+ * privileges of the caller. When used with {@code invokedynamic},
+ * this is stacked automatically by the VM.
+ * @param invokedName The name of the method to implement. When used with
+ * {@code invokedynamic}, this is provided by the
+ * {@code NameAndType} of the {@code InvokeDynamic}
+ * structure and is stacked automatically by the VM.
+ * @param invokedType The expected signature of the {@code CallSite}. The
+ * parameter types represent the types of capture variables;
+ * the return type is the interface to implement. When
+ * used with {@code invokedynamic}, this is provided by
+ * the {@code NameAndType} of the {@code InvokeDynamic}
+ * structure and is stacked automatically by the VM.
* In the event that the implementation method is an
- * instance method, the first argument in the invocation
- * signature will correspond to the receiver.
- * @param samMethodType MethodType of the method in the functional interface
- * to which the lambda or method reference is being
- * converted, represented as a MethodType.
- * @param implMethod The implementation method which should be called
- * (with suitable adaptation of argument types, return
- * types, and adjustment for captured arguments) when
- * methods of the resulting functional interface instance
- * are invoked.
- * @param instantiatedMethodType The signature of the primary functional
- * interface method after type variables
- * are substituted with their instantiation
- * from the capture site
- * @return a CallSite, which, when invoked, will return an instance of the
- * functional interface
- * @throws ReflectiveOperationException if the caller is not able to
- * reconstruct one of the method handles
- * @throws LambdaConversionException If any of the meta-factory protocol
- * invariants are violated
+ * instance method and this signature has any parameters,
+ * the first parameter in the invocation signature must
+ * correspond to the receiver.
+ * @param samMethodType Signature and return type of method to be implemented
+ * by the function object.
+ * @param implMethod A direct method handle describing the implementation
+ * method which should be called (with suitable adaptation
+ * of argument types, return types, and with captured
+ * arguments prepended to the invocation arguments) at
+ * invocation time.
+ * @param instantiatedMethodType The signature and return type that should
+ * be enforced dynamically at invocation time.
+ * This may be the same as {@code samMethodType},
+ * or may be a specialization of it.
+ * @return a CallSite whose target can be used to perform capture, generating
+ * instances of the interface named by {@code invokedType}
+ * @throws LambdaConversionException If any of the linkage invariants
+ * described {@link LambdaMetafactory above}
+ * are violated
*/
public static CallSite metafactory(MethodHandles.Lookup caller,
String invokedName,
@@ -205,7 +294,7 @@
MethodType samMethodType,
MethodHandle implMethod,
MethodType instantiatedMethodType)
- throws ReflectiveOperationException, LambdaConversionException {
+ throws LambdaConversionException {
AbstractValidatingLambdaMetafactory mf;
mf = new InnerClassLambdaMetafactory(caller, invokedType,
invokedName, samMethodType,
@@ -216,60 +305,128 @@
}
/**
- * Alternate meta-factory for conversion of lambda expressions or method
- * references to functional interfaces, which supports serialization and
- * other uncommon options.
+ * Facilitates the creation of simple "function objects" that implement one
+ * or more interfaces by delegation to a provided {@link MethodHandle},
+ * after appropriate type adaptation and partial evaluation of arguments.
+ * Typically used as a bootstrap method for {@code invokedynamic}
+ * call sites, to support the lambda expression and method
+ * reference expression features of the Java Programming Language.
*
- * The declared argument list for this method is:
+ *
This is the general, more flexible metafactory; a streamlined version
+ * is provided by {@link #altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)}.
+ * A general description of the behavior of this method is provided
+ * {@link LambdaMetafactory above}.
*
+ *
The argument list for this method includes three fixed parameters,
+ * corresponding to the parameters automatically stacked by the VM for the
+ * bootstrap method in an {@code invokedynamic} invocation, and an {@code Object[]}
+ * parameter that contains additional parameters. The declared argument
+ * list for this method is:
+ *
+ *
{@code
* CallSite altMetafactory(MethodHandles.Lookup caller,
* String invokedName,
* MethodType invokedType,
* Object... args)
+ * }
*
- * but it behaves as if the argument list is:
+ * but it behaves as if the argument list is as follows:
*
+ *
{@code
* CallSite altMetafactory(MethodHandles.Lookup caller,
* String invokedName,
* MethodType invokedType,
- * MethodType samMethodType
+ * MethodType samMethodType,
* MethodHandle implMethod,
* MethodType instantiatedMethodType,
* int flags,
- * int markerInterfaceCount, // IF flags has MARKERS set
- * Class... markerInterfaces // IF flags has MARKERS set
- * int bridgeCount, // IF flags has BRIDGES set
- * MethodType... bridges // IF flags has BRIDGES set
+ * int markerInterfaceCount, // IF flags has MARKERS set
+ * Class... markerInterfaces, // IF flags has MARKERS set
+ * int bridgeCount, // IF flags has BRIDGES set
+ * MethodType... bridges // IF flags has BRIDGES set
* )
+ * }
*
+ * Arguments that appear in the argument list for
+ * {@link #metafactory(MethodHandles.Lookup, String, MethodType, MethodType, MethodHandle, MethodType)}
+ * have the same specification as in that method. The additional arguments
+ * are interpreted as follows:
+ *
+ * - {@code flags} indicates additional options; this is a bitwise
+ * OR of desired flags. Defined flags are {@link #FLAG_BRIDGES},
+ * {@link #FLAG_MARKERS}, and {@link #FLAG_SERIALIZABLE}.
+ * - {@code markerInterfaceCount} is the number of additional interfaces
+ * the function object should implement, and is present if and only if the
+ * {@code FLAG_MARKERS} flag is set.
+ * - {@code markerInterfaces} is a variable-length list of additional
+ * interfaces to implement, whose length equals {@code markerInterfaceCount},
+ * and is present if and only if the {@code FLAG_MARKERS} flag is set.
+ * - {@code bridgeCount} is the number of additional method signatures
+ * the function object should implement, and is present if and only if
+ * the {@code FLAG_BRIDGES} flag is set.
+ * - {@code bridges} is a variable-length list of additional
+ * methods signatures to implement, whose length equals {@code bridgeCount},
+ * and is present if and only if the {@code FLAG_BRIDGES} flag is set.
+ *
+ *
+ * Each class named by {@code markerInterfaces} is subject to the same
+ * restrictions as {@code Rd}, the return type of {@code invokedType},
+ * as described {@link LambdaMetafactory above}. Each {@code MethodType}
+ * named by {@code bridges} is subject to the same restrictions as
+ * {@code samMethodType}, as described {@link LambdaMetafactory above}.
+ *
+ *
When FLAG_SERIALIZABLE is set in {@code flags}, the function objects
+ * will implement {@code Serializable}, and will have a {@code writeReplace}
+ * method that returns an appropriate {@link SerializedLambda}. The
+ * {@code caller} class must have an appropriate {@code $deserializeLambda$}
+ * method, as described in {@link SerializedLambda}.
*
- * @param caller Stacked automatically by VM; represents a lookup context
- * with the accessibility privileges of the caller.
- * @param invokedName Stacked automatically by VM; the name of the invoked
- * method as it appears at the call site.
- * Used as the name of the functional interface method
- * to which the lambda or method reference is being
- * converted.
- * @param invokedType Stacked automatically by VM; the signature of the
- * invoked method, which includes the expected static
- * type of the returned lambda object, and the static
- * types of the captured arguments for the lambda.
+ *
When the target of the {@code CallSite} returned from this method is
+ * invoked, the resulting function objects are instances of a class with
+ * the following properties:
+ *
+ * - The class implements the interface named by the return type
+ * of {@code invokedType} and any interfaces named by {@code markerInterfaces}
+ * - The class declares methods with the name given by {@code invokedName},
+ * and the signature given by {@code samMethodType} and additional signatures
+ * given by {@code bridges}
+ * - The class may override methods from {@code Object}, and may
+ * implement methods related to serialization.
+ *
+ *
+ * @param caller Represents a lookup context with the accessibility
+ * privileges of the caller. When used with {@code invokedynamic},
+ * this is stacked automatically by the VM.
+ * @param invokedName The name of the method to implement. When used with
+ * {@code invokedynamic}, this is provided by the
+ * {@code NameAndType} of the {@code InvokeDynamic}
+ * structure and is stacked automatically by the VM.
+ * @param invokedType The expected signature of the {@code CallSite}. The
+ * parameter types represent the types of capture variables;
+ * the return type is the interface to implement. When
+ * used with {@code invokedynamic}, this is provided by
+ * the {@code NameAndType} of the {@code InvokeDynamic}
+ * structure and is stacked automatically by the VM.
* In the event that the implementation method is an
- * instance method, the first argument in the invocation
- * signature will correspond to the receiver.
- * @param args flags and optional arguments, as described above
- * @return a CallSite, which, when invoked, will return an instance of the
- * functional interface
- * @throws ReflectiveOperationException if the caller is not able to
- * reconstruct one of the method handles
- * @throws LambdaConversionException If any of the meta-factory protocol
- * invariants are violated
+ * instance method and this signature has any parameters,
+ * the first parameter in the invocation signature must
+ * correspond to the receiver.
+ * @param args An {@code Object[]} array containing the required
+ * arguments {@code samMethodType}, {@code implMethod},
+ * {@code instantiatedMethodType}, {@code flags}, and any
+ * optional arguments, as described
+ * {@link #altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)} above}
+ * @return a CallSite whose target can be used to perform capture, generating
+ * instances of the interface named by {@code invokedType}
+ * @throws LambdaConversionException If any of the linkage invariants
+ * described {@link LambdaMetafactory above}
+ * are violated
*/
public static CallSite altMetafactory(MethodHandles.Lookup caller,
String invokedName,
MethodType invokedType,
Object... args)
- throws ReflectiveOperationException, LambdaConversionException {
+ throws LambdaConversionException {
MethodType samMethodType = (MethodType)args[0];
MethodHandle implMethod = (MethodHandle)args[1];
MethodType instantiatedMethodType = (MethodType)args[2];
@@ -294,15 +451,15 @@
else
bridges = EMPTY_MT_ARRAY;
- boolean foundSerializableSupertype = Serializable.class.isAssignableFrom(invokedType.returnType());
- for (Class> c : markerInterfaces)
- foundSerializableSupertype |= Serializable.class.isAssignableFrom(c);
- boolean isSerializable = ((flags & LambdaMetafactory.FLAG_SERIALIZABLE) != 0)
- || foundSerializableSupertype;
-
- if (isSerializable && !foundSerializableSupertype) {
- markerInterfaces = Arrays.copyOf(markerInterfaces, markerInterfaces.length + 1);
- markerInterfaces[markerInterfaces.length-1] = Serializable.class;
+ boolean isSerializable = ((flags & FLAG_SERIALIZABLE) != 0);
+ if (isSerializable) {
+ boolean foundSerializableSupertype = Serializable.class.isAssignableFrom(invokedType.returnType());
+ for (Class> c : markerInterfaces)
+ foundSerializableSupertype |= Serializable.class.isAssignableFrom(c);
+ if (!foundSerializableSupertype) {
+ markerInterfaces = Arrays.copyOf(markerInterfaces, markerInterfaces.length + 1);
+ markerInterfaces[markerInterfaces.length-1] = Serializable.class;
+ }
}
AbstractValidatingLambdaMetafactory mf
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/invoke/MagicLambdaImpl.java
--- a/src/share/classes/java/lang/invoke/MagicLambdaImpl.java Thu Oct 31 16:22:30 2013 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package java.lang.invoke;
-
-/** MagicLambdaImpl (named for similarity to MagicAccessorImpl and
- others, not because it actually implements an interface) is a
- marker class in the hierarchy. All subclasses of this class are
- "magically" granted access by the VM to otherwise inaccessible
- fields and methods of other classes. It is distinct from MagicAccessorImpl
- because, while we want to bypass accessibility checks, we do not want to
- bypass verification.
-
- Do not change the name of this class without also changing the
- VM's code.
*/
-
-class MagicLambdaImpl {
-}
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/invoke/MethodHandleNatives.java
--- a/src/share/classes/java/lang/invoke/MethodHandleNatives.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/invoke/MethodHandleNatives.java Thu Oct 31 16:44:18 2013 -0700
@@ -441,8 +441,13 @@
assert(refKindIsValid(refKind));
return lookup.linkMethodHandleConstant((byte) refKind, defc, name, type);
} catch (IllegalAccessException ex) {
- Error err = new IllegalAccessError(ex.getMessage());
- throw initCauseFrom(err, ex);
+ Throwable cause = ex.getCause();
+ if (cause instanceof AbstractMethodError) {
+ throw (AbstractMethodError) cause;
+ } else {
+ Error err = new IllegalAccessError(ex.getMessage());
+ throw initCauseFrom(err, ex);
+ }
} catch (NoSuchMethodException ex) {
Error err = new NoSuchMethodError(ex.getMessage());
throw initCauseFrom(err, ex);
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/invoke/MethodHandles.java
--- a/src/share/classes/java/lang/invoke/MethodHandles.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/invoke/MethodHandles.java Thu Oct 31 16:44:18 2013 -0700
@@ -1716,6 +1716,13 @@
checkSymbolicClass(defc);
return mh;
}
+ // Treat MethodHandle.invoke and invokeExact specially.
+ if (defc == MethodHandle.class && refKind == REF_invokeVirtual) {
+ mh = findVirtualForMH(member.getName(), member.getMethodType());
+ if (mh != null) {
+ return mh;
+ }
+ }
MemberName resolved = resolveOrFail(refKind, member);
mh = getDirectMethodForConstant(refKind, defc, resolved);
if (mh instanceof DirectMethodHandle
@@ -1768,12 +1775,6 @@
if (MethodHandleNatives.refKindIsField(refKind)) {
return getDirectFieldNoSecurityManager(refKind, defc, member);
} else if (MethodHandleNatives.refKindIsMethod(refKind)) {
- if (defc == MethodHandle.class && refKind == REF_invokeVirtual) {
- MethodHandle mh = findVirtualForMH(member.getName(), member.getMethodType());
- if (mh != null) {
- return mh;
- }
- }
return getDirectMethodNoSecurityManager(refKind, defc, member, lookupClass);
} else if (refKind == REF_newInvokeSpecial) {
return getDirectConstructorNoSecurityManager(defc, member);
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/invoke/SerializedLambda.java
--- a/src/share/classes/java/lang/invoke/SerializedLambda.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/invoke/SerializedLambda.java Thu Oct 31 16:44:18 2013 -0700
@@ -32,9 +32,26 @@
import java.util.Objects;
/**
- * Serialized form of a lambda expression. The properties of this class represent the information that is present
- * at the lambda factory site, including the identity of the primary functional interface method, the identity of the
- * implementation method, and any variables captured from the local environment at the time of lambda capture.
+ * Serialized form of a lambda expression. The properties of this class
+ * represent the information that is present at the lambda factory site, including
+ * static metafactory arguments such as the identity of the primary functional
+ * interface method and the identity of the implementation method, as well as
+ * dynamic metafactory arguments such as values captured from the lexical scope
+ * at the time of lambda capture.
+ *
+ * Implementors of serializable lambdas, such as compilers or language
+ * runtime libraries, are expected to ensure that instances deserialize properly.
+ * One means to do so is to ensure that the {@code writeReplace} method returns
+ * an instance of {@code SerializedLambda}, rather than allowing default
+ * serialization to proceed.
+ *
+ *
{@code SerializedLambda} has a {@code readResolve} method that looks for
+ * a (possibly private) static method called
+ * {@code $deserializeLambda$(SerializedLambda)} in the capturing class, invokes
+ * that with itself as the first argument, and returns the result. Lambda classes
+ * implementing {@code $deserializeLambda$} are responsible for validating
+ * that the properties of the {@code SerializedLambda} are consistent with a
+ * lambda actually captured by that class.
*
* @see LambdaMetafactory
*/
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java
--- a/src/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java Thu Oct 31 16:44:18 2013 -0700
@@ -28,6 +28,7 @@
import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.Type;
+import sun.invoke.util.BytecodeDescriptor;
import sun.invoke.util.Wrapper;
import static sun.invoke.util.Wrapper.*;
@@ -204,27 +205,27 @@
}
/**
- * Convert an argument of type 'argType' to be passed to 'targetType' assuring that it is 'functionalType'.
+ * Convert an argument of type 'arg' to be passed to 'target' assuring that it is 'functional'.
* Insert the needed conversion instructions in the method code.
- * @param argType
- * @param targetType
- * @param functionalType
+ * @param arg
+ * @param target
+ * @param functional
*/
- void convertType(String dArg, String dTarget, String dFunctional) {
- if (dArg.equals(dTarget)) {
+ void convertType(Class> arg, Class> target, Class> functional) {
+ if (arg.equals(target)) {
return;
}
- Wrapper wArg = toWrapper(dArg);
- Wrapper wTarget = toWrapper(dTarget);
- if (wArg == VOID || wTarget == VOID) {
+ if (arg == Void.TYPE || target == Void.TYPE) {
return;
}
- if (isPrimitive(wArg)) {
- if (isPrimitive(wTarget)) {
+ if (arg.isPrimitive()) {
+ Wrapper wArg = Wrapper.forPrimitiveType(arg);
+ if (target.isPrimitive()) {
// Both primitives: widening
- widen(wArg, wTarget);
+ widen(wArg, Wrapper.forPrimitiveType(target));
} else {
// Primitive argument to reference target
+ String dTarget = BytecodeDescriptor.unparse(target);
Wrapper wPrimTarget = wrapperOrNullFromDescriptor(dTarget);
if (wPrimTarget != null) {
// The target is a boxed primitive type, widen to get there before boxing
@@ -237,16 +238,18 @@
}
}
} else {
+ String dArg = BytecodeDescriptor.unparse(arg);
String dSrc;
- Wrapper wFunctional = toWrapper(dFunctional);
- if (isPrimitive(wFunctional)) {
+ if (functional.isPrimitive()) {
dSrc = dArg;
} else {
// Cast to convert to possibly more specific type, and generate CCE for invalid arg
- dSrc = dFunctional;
- cast(dArg, dFunctional);
+ dSrc = BytecodeDescriptor.unparse(functional);
+ cast(dArg, dSrc);
}
- if (isPrimitive(wTarget)) {
+ String dTarget = BytecodeDescriptor.unparse(target);
+ if (target.isPrimitive()) {
+ Wrapper wTarget = toWrapper(dTarget);
// Reference argument to primitive target
Wrapper wps = wrapperOrNullFromDescriptor(dSrc);
if (wps != null) {
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/management/ManagementFactory.java
--- a/src/share/classes/java/lang/management/ManagementFactory.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/management/ManagementFactory.java Thu Oct 31 16:44:18 2013 -0700
@@ -60,7 +60,7 @@
* one or more platform MXBeans representing
* the management interface of a component of the Java virtual
* machine.
- *
+ *
*
*
* A platform MXBean is a managed bean that
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/management/ManagementPermission.java
--- a/src/share/classes/java/lang/management/ManagementPermission.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/management/ManagementPermission.java Thu Oct 31 16:44:18 2013 -0700
@@ -33,10 +33,8 @@
* The following table
* provides a summary description of what the permission allows,
* and discusses the risks of granting code the permission.
- *
*
- *
+ *
*
* Permission Target Name |
* What the Permission Allows |
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/management/MemoryUsage.java
--- a/src/share/classes/java/lang/management/MemoryUsage.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/management/MemoryUsage.java Thu Oct 31 16:44:18 2013 -0700
@@ -79,7 +79,7 @@
*
*
* Below is a picture showing an example of a memory pool:
- *
+ *
*
* +----------------------------------------------+
* +//////////////// | +
@@ -250,7 +250,7 @@
* Returns a MemoryUsage object represented by the
* given CompositeData. The given CompositeData
* must contain the following attributes:
- *
+ *
*
*
*
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/management/package.html
--- a/src/share/classes/java/lang/management/package.html Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/management/package.html Thu Oct 31 16:44:18 2013 -0700
@@ -82,7 +82,7 @@
1. Direct access to an MXBean interface
-- Get an MXBean instance locally in the running Java virtual machine:
+
- Get an MXBean instance locally in the running Java virtual machine:
RuntimeMXBean mxbean = ManagementFactory.getRuntimeMXBean();
@@ -103,7 +103,7 @@
- Construct an MXBean proxy instance that forwards the
- method calls to a given MBeanServer:
+ method calls to a given MBeanServer:
MBeanServerConnection mbs;
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/reflect/AnnotatedElement.java
--- a/src/share/classes/java/lang/reflect/AnnotatedElement.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/reflect/AnnotatedElement.java Thu Oct 31 16:44:18 2013 -0700
@@ -27,6 +27,15 @@
import java.lang.annotation.Annotation;
import java.lang.annotation.AnnotationFormatError;
+import java.lang.annotation.Repeatable;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import sun.reflect.annotation.AnnotationSupport;
+import sun.reflect.annotation.AnnotationType;
/**
* Represents an annotated element of the program currently running in this
@@ -222,6 +231,18 @@
* The caller of this method is free to modify the returned array; it will
* have no effect on the arrays returned to other callers.
*
+ * @implSpec The default implementation first calls {@link
+ * #getDeclaredAnnotationsByType(Class)} passing {@code
+ * annotationClass} as the argument. If the returned array has
+ * length greater than zero, the array is returned. If the returned
+ * array is zero-length and this {@code AnnotatedElement} is a
+ * class and the argument type is an inheritable annotation type,
+ * and the superclass of this {@code AnnotatedElement} is non-null,
+ * then the returned result is the result of calling {@link
+ * #getAnnotationsByType(Class)} on the superclass with {@code
+ * annotationClass} as the argument. Otherwise, a zero-length
+ * array is returned.
+ *
* @param the type of the annotation to query for and return if present
* @param annotationClass the Class object corresponding to the
* annotation type
@@ -230,7 +251,29 @@
* @throws NullPointerException if the given annotation class is null
* @since 1.8
*/
- T[] getAnnotationsByType(Class annotationClass);
+ default T[] getAnnotationsByType(Class annotationClass) {
+ /*
+ * Definition of associated: directly or indirectly present OR
+ * neither directly nor indirectly present AND the element is
+ * a Class, the annotation type is inheritable, and the
+ * annotation type is associated with the superclass of the
+ * element.
+ */
+ T[] result = getDeclaredAnnotationsByType(annotationClass);
+
+ if (result.length == 0 && // Neither directly nor indirectly present
+ this instanceof Class && // the element is a class
+ AnnotationType.getInstance(annotationClass).isInherited()) { // Inheritable
+ Class> superClass = ((Class>) this).getSuperclass();
+ if (superClass != null) {
+ // Determine if the annotation is associated with the
+ // superclass
+ result = superClass.getAnnotationsByType(annotationClass);
+ }
+ }
+
+ return result;
+ }
/**
* Returns this element's annotation for the specified type if
@@ -239,6 +282,11 @@
* This method ignores inherited annotations. (Returns null if no
* annotations are directly present on this element.)
*
+ * @implSpec The default implementation first performs a null check
+ * and then loops over the results of {@link
+ * #getDeclaredAnnotations} returning the first annotation whose
+ * annotation type matches the argument type.
+ *
* @param the type of the annotation to query for and return if directly present
* @param annotationClass the Class object corresponding to the
* annotation type
@@ -247,7 +295,18 @@
* @throws NullPointerException if the given annotation class is null
* @since 1.8
*/
- T getDeclaredAnnotation(Class annotationClass);
+ default T getDeclaredAnnotation(Class annotationClass) {
+ Objects.requireNonNull(annotationClass);
+ // Loop over all directly-present annotations looking for a matching one
+ for (Annotation annotation : getDeclaredAnnotations()) {
+ if (annotationClass.equals(annotation.annotationType())) {
+ // More robust to do a dynamic cast at runtime instead
+ // of compile-time only.
+ return annotationClass.cast(annotation);
+ }
+ }
+ return null;
+ }
/**
* Returns this element's annotation(s) for the specified type if
@@ -268,6 +327,22 @@
* The caller of this method is free to modify the returned array; it will
* have no effect on the arrays returned to other callers.
*
+ * @implSpec The default implementation may call {@link
+ * #getDeclaredAnnotation(Class)} one or more times to find a
+ * directly present annotation and, if the annotation type is
+ * repeatable, to find a container annotation. If annotations of
+ * the annotation type {@code annotationClass} are found to be both
+ * directly and indirectly present, then {@link
+ * #getDeclaredAnnotations()} will get called to determine the
+ * order of the elements in the returned array.
+ *
+ * Alternatively, the default implementation may call {@link
+ * #getDeclaredAnnotations()} a single time and the returned array
+ * examined for both directly and indirectly present
+ * annotations. The results of calling {@link
+ * #getDeclaredAnnotations()} are assumed to be consistent with the
+ * results of calling {@link #getDeclaredAnnotation(Class)}.
+ *
* @param the type of the annotation to query for and return
* if directly or indirectly present
* @param annotationClass the Class object corresponding to the
@@ -277,7 +352,16 @@
* @throws NullPointerException if the given annotation class is null
* @since 1.8
*/
- T[] getDeclaredAnnotationsByType(Class annotationClass);
+ default T[] getDeclaredAnnotationsByType(Class annotationClass) {
+ Objects.requireNonNull(annotationClass);
+ return AnnotationSupport.
+ getDirectlyAndIndirectlyPresent(Arrays.stream(getDeclaredAnnotations()).
+ collect(Collectors.toMap(Annotation::annotationType,
+ Function.identity(),
+ ((first,second) -> first),
+ LinkedHashMap::new)),
+ annotationClass);
+ }
/**
* Returns annotations that are directly present on this element.
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/reflect/Constructor.java
--- a/src/share/classes/java/lang/reflect/Constructor.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/reflect/Constructor.java Thu Oct 31 16:44:18 2013 -0700
@@ -28,6 +28,8 @@
import sun.reflect.CallerSensitive;
import sun.reflect.ConstructorAccessor;
import sun.reflect.Reflection;
+import sun.reflect.annotation.TypeAnnotation;
+import sun.reflect.annotation.TypeAnnotationParser;
import sun.reflect.generics.repository.ConstructorRepository;
import sun.reflect.generics.factory.CoreReflectionFactory;
import sun.reflect.generics.factory.GenericsFactory;
@@ -534,4 +536,22 @@
public AnnotatedType getAnnotatedReturnType() {
return getAnnotatedReturnType0(getDeclaringClass());
}
+
+ /**
+ * {@inheritDoc}
+ * @since 1.8
+ */
+ @Override
+ public AnnotatedType getAnnotatedReceiverType() {
+ if (getDeclaringClass().getEnclosingClass() == null)
+ return super.getAnnotatedReceiverType();
+
+ return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes0(),
+ sun.misc.SharedSecrets.getJavaLangAccess().
+ getConstantPool(getDeclaringClass()),
+ this,
+ getDeclaringClass(),
+ getDeclaringClass().getEnclosingClass(),
+ TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER);
+ }
}
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/reflect/Executable.java
--- a/src/share/classes/java/lang/reflect/Executable.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/reflect/Executable.java Thu Oct 31 16:44:18 2013 -0700
@@ -383,7 +383,7 @@
private transient volatile Parameter[] parameters;
private native Parameter[] getParameters0();
- private native byte[] getTypeAnnotationBytes0();
+ native byte[] getTypeAnnotationBytes0();
// Needed by reflectaccess
byte[] getTypeAnnotationBytes() {
@@ -527,7 +527,7 @@
public T[] getAnnotationsByType(Class annotationClass) {
Objects.requireNonNull(annotationClass);
- return AnnotationSupport.getMultipleAnnotations(declaredAnnotations(), annotationClass);
+ return AnnotationSupport.getDirectlyAndIndirectlyPresent(declaredAnnotations(), annotationClass);
}
/**
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/reflect/Field.java
--- a/src/share/classes/java/lang/reflect/Field.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/reflect/Field.java Thu Oct 31 16:44:18 2013 -0700
@@ -1123,7 +1123,7 @@
public T[] getAnnotationsByType(Class annotationClass) {
Objects.requireNonNull(annotationClass);
- return AnnotationSupport.getMultipleAnnotations(declaredAnnotations(), annotationClass);
+ return AnnotationSupport.getDirectlyAndIndirectlyPresent(declaredAnnotations(), annotationClass);
}
/**
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/reflect/Parameter.java
--- a/src/share/classes/java/lang/reflect/Parameter.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/reflect/Parameter.java Thu Oct 31 16:44:18 2013 -0700
@@ -295,7 +295,7 @@
public T[] getAnnotationsByType(Class annotationClass) {
Objects.requireNonNull(annotationClass);
- return AnnotationSupport.getMultipleAnnotations(declaredAnnotations(), annotationClass);
+ return AnnotationSupport.getDirectlyAndIndirectlyPresent(declaredAnnotations(), annotationClass);
}
/**
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/lang/reflect/ReflectPermission.java
--- a/src/share/classes/java/lang/reflect/ReflectPermission.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/lang/reflect/ReflectPermission.java Thu Oct 31 16:44:18 2013 -0700
@@ -31,7 +31,6 @@
* The following table
* provides a summary description of what the permission allows,
* and discusses the risks of granting code the permission.
- *
*
*
*
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/math/BigInteger.java
--- a/src/share/classes/java/math/BigInteger.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/math/BigInteger.java Thu Oct 31 16:44:18 2013 -0700
@@ -97,6 +97,21 @@
* {@code NullPointerException} when passed
* a null object reference for any input parameter.
*
+ * BigInteger must support values in the range
+ * -2{@code Integer.MAX_VALUE} (exclusive) to
+ * +2{@code Integer.MAX_VALUE} (exclusive)
+ * and may support values outside of that range.
+ *
+ * The range of probable prime values is limited and may be less than
+ * the full supported positive range of {@code BigInteger}.
+ * The range must be at least 1 to 2500000000.
+ *
+ * @implNote
+ * BigInteger constructors and operations throw {@code ArithmeticException} when
+ * the result is out of the supported range of
+ * -2{@code Integer.MAX_VALUE} (exclusive) to
+ * +2{@code Integer.MAX_VALUE} (exclusive).
+ *
* @see BigDecimal
* @author Josh Bloch
* @author Michael McCloskey
@@ -183,6 +198,18 @@
final static long LONG_MASK = 0xffffffffL;
/**
+ * This constant limits {@code mag.length} of BigIntegers to the supported
+ * range.
+ */
+ private static final int MAX_MAG_LENGTH = Integer.MAX_VALUE / Integer.SIZE + 1; // (1 << 26)
+
+ /**
+ * Bit lengths larger than this constant can cause overflow in searchLen
+ * calculation and in BitSieve.singleSearch method.
+ */
+ private static final int PRIME_SEARCH_BIT_LENGTH_LIMIT = 500000000;
+
+ /**
* The threshold value for using Karatsuba multiplication. If the number
* of ints in both mag arrays are greater than this number, then
* Karatsuba multiplication will be used. This value is found
@@ -256,6 +283,9 @@
mag = stripLeadingZeroBytes(val);
signum = (mag.length == 0 ? 0 : 1);
}
+ if (mag.length >= MAX_MAG_LENGTH) {
+ checkRange();
+ }
}
/**
@@ -275,6 +305,9 @@
mag = trustedStripLeadingZeroInts(val);
signum = (mag.length == 0 ? 0 : 1);
}
+ if (mag.length >= MAX_MAG_LENGTH) {
+ checkRange();
+ }
}
/**
@@ -306,6 +339,9 @@
throw(new NumberFormatException("signum-magnitude mismatch"));
this.signum = signum;
}
+ if (mag.length >= MAX_MAG_LENGTH) {
+ checkRange();
+ }
}
/**
@@ -327,6 +363,9 @@
throw(new NumberFormatException("signum-magnitude mismatch"));
this.signum = signum;
}
+ if (mag.length >= MAX_MAG_LENGTH) {
+ checkRange();
+ }
}
/**
@@ -359,17 +398,20 @@
int sign = 1;
int index1 = val.lastIndexOf('-');
int index2 = val.lastIndexOf('+');
- if ((index1 + index2) <= -1) {
- // No leading sign character or at most one leading sign character
- if (index1 == 0 || index2 == 0) {
- cursor = 1;
- if (len == 1)
- throw new NumberFormatException("Zero length BigInteger");
+ if (index1 >= 0) {
+ if (index1 != 0 || index2 >= 0) {
+ throw new NumberFormatException("Illegal embedded sign character");
}
- if (index1 == 0)
- sign = -1;
- } else
- throw new NumberFormatException("Illegal embedded sign character");
+ sign = -1;
+ cursor = 1;
+ } else if (index2 >= 0) {
+ if (index2 != 0) {
+ throw new NumberFormatException("Illegal embedded sign character");
+ }
+ cursor = 1;
+ }
+ if (cursor == len)
+ throw new NumberFormatException("Zero length BigInteger");
// Skip leading zeros and compute number of digits in magnitude
while (cursor < len &&
@@ -388,8 +430,11 @@
// Pre-allocate array of expected size. May be too large but can
// never be too small. Typically exact.
- int numBits = (int)(((numDigits * bitsPerDigit[radix]) >>> 10) + 1);
- int numWords = (numBits + 31) >>> 5;
+ long numBits = ((numDigits * bitsPerDigit[radix]) >>> 10) + 1;
+ if (numBits + 31 >= (1L << 32)) {
+ reportOverflow();
+ }
+ int numWords = (int) (numBits + 31) >>> 5;
int[] magnitude = new int[numWords];
// Process first (potentially short) digit group
@@ -413,6 +458,9 @@
}
// Required for cases where the array was overallocated.
mag = trustedStripLeadingZeroInts(magnitude);
+ if (mag.length >= MAX_MAG_LENGTH) {
+ checkRange();
+ }
}
/*
@@ -439,8 +487,11 @@
if (len < 10) {
numWords = 1;
} else {
- int numBits = (int)(((numDigits * bitsPerDigit[10]) >>> 10) + 1);
- numWords = (numBits + 31) >>> 5;
+ long numBits = ((numDigits * bitsPerDigit[10]) >>> 10) + 1;
+ if (numBits + 31 >= (1L << 32)) {
+ reportOverflow();
+ }
+ numWords = (int) (numBits + 31) >>> 5;
}
int[] magnitude = new int[numWords];
@@ -456,6 +507,9 @@
destructiveMulAdd(magnitude, intRadix[10], groupVal);
}
mag = trustedStripLeadingZeroInts(magnitude);
+ if (mag.length >= MAX_MAG_LENGTH) {
+ checkRange();
+ }
}
// Create an integer with the digits between the two indexes
@@ -575,7 +629,7 @@
* this constructor is proportional to the value of this parameter.
* @param rnd source of random bits used to select candidates to be
* tested for primality.
- * @throws ArithmeticException {@code bitLength < 2}.
+ * @throws ArithmeticException {@code bitLength < 2} or {@code bitLength} is too large.
* @see #bitLength()
*/
public BigInteger(int bitLength, int certainty, Random rnd) {
@@ -607,7 +661,7 @@
* @param rnd source of random bits used to select candidates to be
* tested for primality.
* @return a BigInteger of {@code bitLength} bits that is probably prime
- * @throws ArithmeticException {@code bitLength < 2}.
+ * @throws ArithmeticException {@code bitLength < 2} or {@code bitLength} is too large.
* @see #bitLength()
* @since 1.4
*/
@@ -677,7 +731,7 @@
p.mag[p.mag.length-1] &= 0xfffffffe;
// Use a sieve length likely to contain the next prime number
- int searchLen = (bitLength / 20) * 64;
+ int searchLen = getPrimeSearchLen(bitLength);
BitSieve searchSieve = new BitSieve(p, searchLen);
BigInteger candidate = searchSieve.retrieve(p, certainty, rnd);
@@ -701,7 +755,7 @@
*
* @return the first integer greater than this {@code BigInteger} that
* is probably prime.
- * @throws ArithmeticException {@code this < 0}.
+ * @throws ArithmeticException {@code this < 0} or {@code this} is too large.
* @since 1.5
*/
public BigInteger nextProbablePrime() {
@@ -750,7 +804,7 @@
result = result.subtract(ONE);
// Looking for the next large prime
- int searchLen = (result.bitLength() / 20) * 64;
+ int searchLen = getPrimeSearchLen(result.bitLength());
while (true) {
BitSieve searchSieve = new BitSieve(result, searchLen);
@@ -762,6 +816,13 @@
}
}
+ private static int getPrimeSearchLen(int bitLength) {
+ if (bitLength > PRIME_SEARCH_BIT_LENGTH_LIMIT + 1) {
+ throw new ArithmeticException("Prime search implementation restriction on bitLength");
+ }
+ return bitLength / 20 * 64;
+ }
+
/**
* Returns {@code true} if this BigInteger is probably prime,
* {@code false} if it's definitely composite.
@@ -965,6 +1026,9 @@
BigInteger(int[] magnitude, int signum) {
this.signum = (magnitude.length == 0 ? 0 : signum);
this.mag = magnitude;
+ if (mag.length >= MAX_MAG_LENGTH) {
+ checkRange();
+ }
}
/**
@@ -974,6 +1038,25 @@
private BigInteger(byte[] magnitude, int signum) {
this.signum = (magnitude.length == 0 ? 0 : signum);
this.mag = stripLeadingZeroBytes(magnitude);
+ if (mag.length >= MAX_MAG_LENGTH) {
+ checkRange();
+ }
+ }
+
+ /**
+ * Throws an {@code ArithmeticException} if the {@code BigInteger} would be
+ * out of the supported range.
+ *
+ * @throws ArithmeticException if {@code this} exceeds the supported range.
+ */
+ private void checkRange() {
+ if (mag.length > MAX_MAG_LENGTH || mag.length == MAX_MAG_LENGTH && mag[0] < 0) {
+ reportOverflow();
+ }
+ }
+
+ private static void reportOverflow() {
+ throw new ArithmeticException("BigInteger would overflow supported range");
}
//Static Factory Methods
@@ -2073,6 +2156,10 @@
// The remaining part can then be exponentiated faster. The
// powers of two will be multiplied back at the end.
int powersOfTwo = partToSquare.getLowestSetBit();
+ long bitsToShift = (long)powersOfTwo * exponent;
+ if (bitsToShift > Integer.MAX_VALUE) {
+ reportOverflow();
+ }
int remainingBits;
@@ -2126,11 +2213,10 @@
// Multiply back the powers of two (quickly, by shifting left)
if (powersOfTwo > 0) {
- int bitsToShift = powersOfTwo*exponent;
if (bitsToShift + scaleFactor <= 62) { // Fits in long?
return valueOf((result << bitsToShift) * newSign);
} else {
- return valueOf(result*newSign).shiftLeft(bitsToShift);
+ return valueOf(result*newSign).shiftLeft((int) bitsToShift);
}
}
else {
@@ -2375,8 +2461,17 @@
BigInteger y1 = m2.modInverse(m1);
BigInteger y2 = m1.modInverse(m2);
- result = a1.multiply(m2).multiply(y1).add
- (a2.multiply(m1).multiply(y2)).mod(m);
+ if (m.mag.length < MAX_MAG_LENGTH / 2) {
+ result = a1.multiply(m2).multiply(y1).add(a2.multiply(m1).multiply(y2)).mod(m);
+ } else {
+ MutableBigInteger t1 = new MutableBigInteger();
+ new MutableBigInteger(a1.multiply(m2)).multiply(new MutableBigInteger(y1), t1);
+ MutableBigInteger t2 = new MutableBigInteger();
+ new MutableBigInteger(a2.multiply(m1)).multiply(new MutableBigInteger(y2), t2);
+ t1.add(t2);
+ MutableBigInteger q = new MutableBigInteger();
+ result = t1.divide(new MutableBigInteger(m), q).toBigInteger();
+ }
}
return (invertResult ? result.modInverse(m) : result);
@@ -2797,27 +2892,31 @@
*
* @param n shift distance, in bits.
* @return {@code this << n}
- * @throws ArithmeticException if the shift distance is {@code
- * Integer.MIN_VALUE}.
* @see #shiftRight
*/
public BigInteger shiftLeft(int n) {
if (signum == 0)
return ZERO;
- if (n == 0)
+ if (n > 0) {
+ return new BigInteger(shiftLeft(mag, n), signum);
+ } else if (n == 0) {
return this;
- if (n < 0) {
- if (n == Integer.MIN_VALUE) {
- throw new ArithmeticException("Shift distance of Integer.MIN_VALUE not supported.");
- } else {
- return shiftRight(-n);
- }
+ } else {
+ // Possible int overflow in (-n) is not a trouble,
+ // because shiftRightImpl considers its argument unsigned
+ return shiftRightImpl(-n);
}
- int[] newMag = shiftLeft(mag, n);
-
- return new BigInteger(newMag, signum);
}
+ /**
+ * Returns a magnitude array whose value is {@code (mag << n)}.
+ * The shift distance, {@code n}, is considered unnsigned.
+ * (Computes this * 2n.)
+ *
+ * @param mag magnitude, the most-significant int ({@code mag[0]}) must be non-zero.
+ * @param n unsigned shift distance, in bits.
+ * @return {@code mag << n}
+ */
private static int[] shiftLeft(int[] mag, int n) {
int nInts = n >>> 5;
int nBits = n & 0x1f;
@@ -2853,21 +2952,31 @@
*
* @param n shift distance, in bits.
* @return {@code this >> n}
- * @throws ArithmeticException if the shift distance is {@code
- * Integer.MIN_VALUE}.
* @see #shiftLeft
*/
public BigInteger shiftRight(int n) {
- if (n == 0)
+ if (signum == 0)
+ return ZERO;
+ if (n > 0) {
+ return shiftRightImpl(n);
+ } else if (n == 0) {
return this;
- if (n < 0) {
- if (n == Integer.MIN_VALUE) {
- throw new ArithmeticException("Shift distance of Integer.MIN_VALUE not supported.");
- } else {
- return shiftLeft(-n);
- }
+ } else {
+ // Possible int overflow in {@code -n} is not a trouble,
+ // because shiftLeft considers its argument unsigned
+ return new BigInteger(shiftLeft(mag, -n), signum);
}
-
+ }
+
+ /**
+ * Returns a BigInteger whose value is {@code (this >> n)}. The shift
+ * distance, {@code n}, is considered unsigned.
+ * (Computes floor(this * 2-n).)
+ *
+ * @param n unsigned shift distance, in bits.
+ * @return {@code this >> n}
+ */
+ private BigInteger shiftRightImpl(int n) {
int nInts = n >>> 5;
int nBits = n & 0x1f;
int magLen = mag.length;
@@ -3899,7 +4008,7 @@
;
int extraByte = (k == byteLength) ? 1 : 0;
- int intLength = ((byteLength - keep + extraByte) + 3)/4;
+ int intLength = ((byteLength - keep + extraByte) + 3) >>> 2;
int result[] = new int[intLength];
/* Copy one's complement of input into output, leaving extra
@@ -4135,7 +4244,8 @@
message = "BigInteger: Signum not present in stream";
throw new java.io.StreamCorruptedException(message);
}
- if ((magnitude.length == 0) != (sign == 0)) {
+ int[] mag = stripLeadingZeroBytes(magnitude);
+ if ((mag.length == 0) != (sign == 0)) {
String message = "BigInteger: signum-magnitude mismatch";
if (fields.defaulted("magnitude"))
message = "BigInteger: Magnitude not present in stream";
@@ -4146,7 +4256,14 @@
UnsafeHolder.putSign(this, sign);
// Calculate mag field from magnitude and discard magnitude
- UnsafeHolder.putMag(this, stripLeadingZeroBytes(magnitude));
+ UnsafeHolder.putMag(this, mag);
+ if (mag.length >= MAX_MAG_LENGTH) {
+ try {
+ checkRange();
+ } catch (ArithmeticException e) {
+ throw new java.io.StreamCorruptedException("BigInteger: Out of the supported range");
+ }
+ }
}
// Support for resetting final fields while deserializing
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/math/MutableBigInteger.java
--- a/src/share/classes/java/math/MutableBigInteger.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/math/MutableBigInteger.java Thu Oct 31 16:44:18 2013 -0700
@@ -1257,14 +1257,14 @@
int j = (s+m-1) / m; // step 2a: j = ceil(s/m)
int n = j * m; // step 2b: block length in 32-bit units
- int n32 = 32 * n; // block length in bits
- int sigma = Math.max(0, n32 - b.bitLength()); // step 3: sigma = max{T | (2^T)*B < beta^n}
+ long n32 = 32L * n; // block length in bits
+ int sigma = (int) Math.max(0, n32 - b.bitLength()); // step 3: sigma = max{T | (2^T)*B < beta^n}
MutableBigInteger bShifted = new MutableBigInteger(b);
bShifted.safeLeftShift(sigma); // step 4a: shift b so its length is a multiple of n
safeLeftShift(sigma); // step 4b: shift this by the same amount
// step 5: t is the number of blocks needed to accommodate this plus one additional bit
- int t = (bitLength()+n32) / n32;
+ int t = (int) ((bitLength()+n32) / n32);
if (t < 2) {
t = 2;
}
@@ -1421,10 +1421,10 @@
}
/** @see BigInteger#bitLength() */
- int bitLength() {
+ long bitLength() {
if (intLen == 0)
return 0;
- return intLen*32 - Integer.numberOfLeadingZeros(value[offset]);
+ return intLen*32L - Integer.numberOfLeadingZeros(value[offset]);
}
/**
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/net/DatagramSocket.java
--- a/src/share/classes/java/net/DatagramSocket.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/net/DatagramSocket.java Thu Oct 31 16:44:18 2013 -0700
@@ -196,7 +196,7 @@
* socket address.
*
* If, if the address is {@code null}, creates an unbound socket.
- *
+ *
*
If there is a security manager,
* its {@code checkListen} method is first called
* with the port from the socket address
@@ -1109,7 +1109,7 @@
* represent the value of the TOS octet in IP packets sent by
* the socket.
* RFC 1349 defines the TOS values as follows:
- *
+ *
*
* IPTOS_LOWCOST (0x02)
* IPTOS_RELIABILITY (0x04)
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/net/HttpCookie.java
--- a/src/share/classes/java/net/HttpCookie.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/net/HttpCookie.java Thu Oct 31 16:44:18 2013 -0700
@@ -761,7 +761,7 @@
// from RFC 2068, token special case characters
//
// private static final String tspecials = "()<>@,;:\\\"/[]?={} \t";
- private static final String tspecials = ",;";
+ private static final String tspecials = ",; "; // deliberately includes space
/*
* Tests a string and returns true if the string counts as a token.
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/net/Inet6Address.java
--- a/src/share/classes/java/net/Inet6Address.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/net/Inet6Address.java Thu Oct 31 16:44:18 2013 -0700
@@ -133,7 +133,7 @@
* representation. However, it will be converted into an IPv4
* address.
*
- *
+ *
*
*
* The textual representation of IPv6 addresses as described above can be
@@ -150,11 +150,11 @@
*
*
The general format for specifying the scope_id is the following:
*
- *
IPv6-address%scope_id
+ * IPv6-address%scope_id
* The IPv6-address is a literal IPv6 address as described above.
* The scope_id refers to an interface on the local system, and it can be
* specified in two ways.
- *
- As a numeric identifier. This must be a positive integer
+ *
- As a numeric identifier. This must be a positive integer
* that identifies the particular interface and scope as understood by the
* system. Usually, the numeric values can be determined through administration
* tools on the system. Each interface may have multiple values, one for each
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/net/MulticastSocket.java
--- a/src/share/classes/java/net/MulticastSocket.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/net/MulticastSocket.java Thu Oct 31 16:44:18 2013 -0700
@@ -140,7 +140,7 @@
* Create a MulticastSocket bound to the specified socket address.
*
* Or, if the address is {@code null}, create an unbound socket.
- *
+ *
*
If there is a security manager,
* its {@code checkListen} method is first called
* with the SocketAddress port as its argument to ensure the operation is allowed.
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/net/NetPermission.java
--- a/src/share/classes/java/net/NetPermission.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/net/NetPermission.java Thu Oct 31 16:44:18 2013 -0700
@@ -46,7 +46,6 @@
* The following table lists all the possible NetPermission target names,
* and for each provides a description of what the permission allows
* and a discussion of the risks of granting code the permission.
- *
*
*
*
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/net/Proxy.java
--- a/src/share/classes/java/net/Proxy.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/net/Proxy.java Thu Oct 31 16:44:18 2013 -0700
@@ -66,8 +66,8 @@
* Used, for instance, to create sockets bypassing any other global
* proxy settings (like SOCKS):
*
- * {@code Socket s = new Socket(Proxy.NO_PROXY);}
- *
+ * {@code Socket s = new Socket(Proxy.NO_PROXY);}
+ *
*/
public final static Proxy NO_PROXY = new Proxy();
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/net/Socket.java
--- a/src/share/classes/java/net/Socket.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/net/Socket.java Thu Oct 31 16:44:18 2013 -0700
@@ -1230,13 +1230,13 @@
* Generally, the window size can be modified at any time when a socket is
* connected. However, if a receive window larger than 64K is required then
* this must be requested before the socket is connected to the
- * remote peer. There are two cases to be aware of:
+ * remote peer. There are two cases to be aware of:
*
* - For sockets accepted from a ServerSocket, this must be done by calling
* {@link ServerSocket#setReceiveBufferSize(int)} before the ServerSocket
* is bound to a local address.
* - For client sockets, setReceiveBufferSize() must be called before
- * connecting the socket to its remote peer.
+ * connecting the socket to its remote peer.
* @param size the size to which to set the receive buffer
* size. This value must be greater than 0.
*
@@ -1329,7 +1329,7 @@
* represent the value of the TOS octet in IP packets sent by
* the socket.
* RFC 1349 defines the TOS values as follows:
- *
+ *
*
* IPTOS_LOWCOST (0x02)
* IPTOS_RELIABILITY (0x04)
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/net/SocketOptions.java
--- a/src/share/classes/java/net/SocketOptions.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/net/SocketOptions.java Thu Oct 31 16:44:18 2013 -0700
@@ -134,7 +134,7 @@
* previously written data.
*
* Valid for TCP only: SocketImpl.
- *
+ *
* @see Socket#setTcpNoDelay
* @see Socket#getTcpNoDelay
*/
@@ -155,7 +155,7 @@
* This option must be specified in the constructor.
*
* Valid for: SocketImpl, DatagramSocketImpl
- *
+ *
* @see Socket#getLocalAddress
* @see DatagramSocket#getLocalAddress
*/
@@ -186,7 +186,7 @@
* want to use other than the system default. Takes/returns an InetAddress.
*
* Valid for Multicast: DatagramSocketImpl
- *
+ *
* @see MulticastSocket#setInterface(InetAddress)
* @see MulticastSocket#getInterface()
*/
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/net/SocketPermission.java
--- a/src/share/classes/java/net/SocketPermission.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/net/SocketPermission.java Thu Oct 31 16:44:18 2013 -0700
@@ -779,27 +779,27 @@
* specified permission.
*
* More specifically, this method first ensures that all of the following
- * are true (and returns false if any of them are not):
+ * are true (and returns false if any of them are not):
*
- * - p is an instanceof SocketPermission,
+ *
- p is an instanceof SocketPermission,
*
- p's actions are a proper subset of this
- * object's actions, and
+ * object's actions, and
*
- p's port range is included in this port range. Note:
- * port range is ignored when p only contains the action, 'resolve'.
+ * port range is ignored when p only contains the action, 'resolve'.
*
*
* Then {@code implies} checks each of the following, in order,
- * and for each returns true if the stated condition is true:
+ * and for each returns true if the stated condition is true:
*
* - If this object was initialized with a single IP address and one of p's
- * IP addresses is equal to this object's IP address.
+ * IP addresses is equal to this object's IP address.
*
- If this object is a wildcard domain (such as *.sun.com), and
* p's canonical name (the name without any preceding *)
* ends with this object's canonical host name. For example, *.sun.com
- * implies *.eng.sun.com..
+ * implies *.eng.sun.com.
*
- If this object was not initialized with a single IP address, and one of this
- * object's IP addresses equals one of p's IP addresses.
- *
- If this canonical name equals p's canonical name.
+ * object's IP addresses equals one of p's IP addresses.
+ *
- If this canonical name equals p's canonical name.
*
*
* If none of the above are true, {@code implies} returns false.
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/net/URI.java
--- a/src/share/classes/java/net/URI.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/net/URI.java Thu Oct 31 16:44:18 2013 -0700
@@ -389,20 +389,20 @@
* colon following a host name but no port (as in
* {@code http://java.sun.com:} ), and that does not encode characters
* except those that must be quoted, the following identities also hold:
- *
+ *
* new URI(u.getScheme(),
* u.getSchemeSpecificPart(),
* u.getFragment())
* .equals(u)
* in all cases,
- *
+ *
* new URI(u.getScheme(),
* u.getUserInfo(), u.getAuthority(),
* u.getPath(), u.getQuery(),
* u.getFragment())
* .equals(u)
* if u is hierarchical, and
- *
+ *
* new URI(u.getScheme(),
* u.getUserInfo(), u.getHost(), u.getPort(),
* u.getPath(), u.getQuery(),
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/net/URLClassLoader.java
--- a/src/share/classes/java/net/URLClassLoader.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/net/URLClassLoader.java Thu Oct 31 16:44:18 2013 -0700
@@ -25,21 +25,30 @@
package java.net;
-import java.io.*;
-import java.util.*;
-import java.util.jar.Manifest;
-import java.util.jar.JarFile;
-import java.util.jar.Attributes;
-import java.util.jar.Attributes.Name;
+import java.io.Closeable;
+import java.io.File;
+import java.io.FilePermission;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.AccessControlContext;
+import java.security.AccessController;
import java.security.CodeSigner;
-import java.security.PrivilegedAction;
-import java.security.PrivilegedExceptionAction;
-import java.security.AccessController;
-import java.security.AccessControlContext;
-import java.security.SecureClassLoader;
import java.security.CodeSource;
import java.security.Permission;
import java.security.PermissionCollection;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedExceptionAction;
+import java.security.SecureClassLoader;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.util.Set;
+import java.util.WeakHashMap;
+import java.util.jar.Attributes;
+import java.util.jar.Attributes.Name;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
import sun.misc.Resource;
import sun.misc.URLClassPath;
import sun.net.www.ParseUtil;
@@ -84,6 +93,7 @@
* @exception SecurityException if a security manager exists and its
* {@code checkCreateClassLoader} method doesn't allow
* creation of a class loader.
+ * @exception NullPointerException if {@code urls} is {@code null}.
* @see SecurityManager#checkCreateClassLoader
*/
public URLClassLoader(URL[] urls, ClassLoader parent) {
@@ -127,6 +137,7 @@
* @exception SecurityException if a security manager exists and its
* {@code checkCreateClassLoader} method doesn't allow
* creation of a class loader.
+ * @exception NullPointerException if {@code urls} is {@code null}.
* @see SecurityManager#checkCreateClassLoader
*/
public URLClassLoader(URL[] urls) {
@@ -169,6 +180,7 @@
* @exception SecurityException if a security manager exists and its
* {@code checkCreateClassLoader} method doesn't allow
* creation of a class loader.
+ * @exception NullPointerException if {@code urls} is {@code null}.
* @see SecurityManager#checkCreateClassLoader
*/
public URLClassLoader(URL[] urls, ClassLoader parent,
@@ -260,13 +272,13 @@
* and errors are not caught. Calling close on an already closed
* loader has no effect.
*
- * @throws IOException if closing any file opened by this class loader
+ * @exception IOException if closing any file opened by this class loader
* resulted in an IOException. Any such exceptions are caught internally.
* If only one is caught, then it is re-thrown. If more than one exception
* is caught, then the second and following exceptions are added
* as suppressed exceptions of the first one caught, which is then re-thrown.
*
- * @throws SecurityException if a security manager is set, and it denies
+ * @exception SecurityException if a security manager is set, and it denies
* {@link RuntimePermission}{@code ("closeClassLoader")}
*
* @since 1.7
@@ -339,6 +351,7 @@
* @return the resulting class
* @exception ClassNotFoundException if the class could not be found,
* or if the loader is closed.
+ * @exception NullPointerException if {@code name} is {@code null}.
*/
protected Class> findClass(final String name)
throws ClassNotFoundException
@@ -621,6 +634,7 @@
* If the protocol is not "file", then permission
* to connect to and accept connections from the URL's host is granted.
* @param codesource the codesource
+ * @exception NullPointerException if {@code codesource} is {@code null}.
* @return the permissions granted to the codesource
*/
protected PermissionCollection getPermissions(CodeSource codesource)
@@ -700,6 +714,7 @@
*
* @param urls the URLs to search for classes and resources
* @param parent the parent class loader for delegation
+ * @exception NullPointerException if {@code urls} is {@code null}.
* @return the resulting class loader
*/
public static URLClassLoader newInstance(final URL[] urls,
@@ -725,6 +740,7 @@
* loading the class.
*
* @param urls the URLs to search for classes and resources
+ * @exception NullPointerException if {@code urls} is {@code null}.
* @return the resulting class loader
*/
public static URLClassLoader newInstance(final URL[] urls) {
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/net/URLConnection.java
--- a/src/share/classes/java/net/URLConnection.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/net/URLConnection.java Thu Oct 31 16:44:18 2013 -0700
@@ -45,7 +45,7 @@
* application and a URL. Instances of this class can be used both to
* read from and to write to the resource referenced by the URL. In
* general, creating a connection to a URL is a multistep process:
- *
+ *
*
* {@code openConnection()} |
* {@code connect()} |
diff -r 6f436140049d -r f82b730c798b src/share/classes/java/net/URLDecoder.java
--- a/src/share/classes/java/net/URLDecoder.java Thu Oct 31 16:22:30 2013 -0700
+++ b/src/share/classes/java/net/URLDecoder.java Thu Oct 31 16:44:18 2013 -0700
@@ -43,7 +43,7 @@
* as the start of a special escaped sequence.
*
* The following rules are applied in the conversion:
- *
+ *
*