diff --git a/jdk/src/share/classes/java/dyn/CallSite.java b/jdk/src/share/classes/java/dyn/CallSite.java index c3b7962911f..7c4ed52ea68 100644 --- a/jdk/src/share/classes/java/dyn/CallSite.java +++ b/jdk/src/share/classes/java/dyn/CallSite.java @@ -273,15 +273,19 @@ public class CallSite public final MethodHandle dynamicInvoker() { if (this instanceof ConstantCallSite) return getTarget(); // will not change dynamically - MethodHandle getCSTarget = GET_TARGET; - if (getCSTarget == null) - GET_TARGET = getCSTarget = MethodHandles.Lookup.IMPL_LOOKUP. - findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class)); - MethodHandle getTarget = MethodHandleImpl.bindReceiver(IMPL_TOKEN, getCSTarget, this); + MethodHandle getTarget = MethodHandleImpl.bindReceiver(IMPL_TOKEN, GET_TARGET, this); MethodHandle invoker = MethodHandles.exactInvoker(this.type()); return MethodHandles.foldArguments(invoker, getTarget); } - private static MethodHandle GET_TARGET = null; // link this lazily, not eagerly + private static final MethodHandle GET_TARGET; + static { + try { + GET_TARGET = MethodHandles.Lookup.IMPL_LOOKUP. + findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class)); + } catch (NoAccessException ignore) { + throw new InternalError(); + } + } /** Implementation of {@link MethodHandleProvider} which returns {@code this.dynamicInvoker()}. */ public final MethodHandle asMethodHandle() { return dynamicInvoker(); } diff --git a/jdk/src/share/classes/java/dyn/MethodHandles.java b/jdk/src/share/classes/java/dyn/MethodHandles.java index ac35f88e143..957d1c18af6 100644 --- a/jdk/src/share/classes/java/dyn/MethodHandles.java +++ b/jdk/src/share/classes/java/dyn/MethodHandles.java @@ -81,6 +81,14 @@ public class MethodHandles { * Return a {@link Lookup lookup object} which is trusted minimally. * It can only be used to create method handles to * publicly accessible fields and methods. + *
+ * As a matter of pure convention, the {@linkplain Lookup#lookupClass lookup class} + * of this lookup object will be {@link java.lang.Object}. + *
+ * The lookup class can be changed to any other class {@code C} using an expression of the form
+ * {@linkplain Lookup#in publicLookup().in(C.class)}.
+ * Since all classes have equal access to public names,
+ * such a change would confer no new access rights.
*/
public static Lookup publicLookup() {
return Lookup.PUBLIC_LOOKUP;
@@ -90,9 +98,10 @@ public class MethodHandles {
* A lookup object is a factory for creating method handles,
* when the creation requires access checking.
* Method handles do not perform
- * access checks when they are called; this is a major difference
+ * access checks when they are called, but rather when they are created.
+ * (This is a major difference
* from reflective {@link Method}, which performs access checking
- * against every caller, on every call.
+ * against every caller, on every call.)
* Therefore, method handle access
* restrictions must be enforced when a method handle is created.
* The caller class against which those restrictions are enforced
@@ -107,7 +116,7 @@ public class MethodHandles {
* It may then use this factory to create method handles on
* all of its methods, including private ones.
* It may also delegate the lookup (e.g., to a metaobject protocol)
- * by passing the {@code Lookup} object to other code.
+ * by passing the lookup object to other code.
* If this other code creates method handles, they will be access
* checked against the original lookup class, and not with any higher
* privileges.
@@ -125,23 +134,28 @@ public class MethodHandles {
* It can also fail if a security manager is installed and refuses
* access. In any of these cases, an exception will be
* thrown from the attempted lookup.
+ *
* In general, the conditions under which a method handle may be * created for a method {@code M} are exactly as restrictive as the conditions * under which the lookup class could have compiled a call to {@code M}. - * At least some of these error conditions are likely to be - * represented by checked exceptions in the final version of this API. + * This rule is applied even if the Java compiler might have created + * an wrapper method to access a private method of another class + * in the same top-level declaration. + * For example, a lookup object created for a nested class {@code C.D} + * can access private members within other related classes such as + * {@code C}, {@code C.D.E}, or {@code C.B}. */ public static final class Lookup { /** The class on behalf of whom the lookup is being performed. */ private final Class> lookupClass; - /** The allowed sorts of members which may be looked up (public, etc.), with STRICT for package. */ + /** The allowed sorts of members which may be looked up (public, etc.), with STATIC for package. */ private final int allowedModes; private static final int PUBLIC = Modifier.PUBLIC, - PACKAGE = Modifier.STRICT, + PACKAGE = Modifier.STATIC, PROTECTED = Modifier.PROTECTED, PRIVATE = Modifier.PRIVATE, ALL_MODES = (PUBLIC | PACKAGE | PROTECTED | PRIVATE), @@ -155,8 +169,10 @@ public class MethodHandles { /** Which class is performing the lookup? It is this class against * which checks are performed for visibility and access permissions. *
- * This value is null if and only if this lookup was produced - * by {@link MethodHandles#publicLookup}. + * The class implies a maximum level of access permission, + * but the permissions may be additionally limited by the bitmask + * {@link #lookupModes}, which controls whether non-public members + * can be accessed. */ public Class> lookupClass() { return lookupClass; @@ -168,10 +184,15 @@ public class MethodHandles { } /** Which types of members can this lookup object produce? - * The result is a bit-mask of the modifier bits PUBLIC, PROTECTED, PRIVATE, and STRICT. - * The modifier bit STRICT stands in for the (non-existent) package protection mode. + * The result is a bit-mask of the {@link Modifier} bits + * {@linkplain Modifier#PUBLIC PUBLIC (0x01)}, + * {@linkplain Modifier#PROTECTED PROTECTED (0x02)}, + * {@linkplain Modifier#PRIVATE PRIVATE (0x04)}, + * and {@linkplain Modifier#STATIC STATIC (0x08)}. + * The modifier bit {@code STATIC} stands in for the package protection mode, + * which does not have an explicit modifier bit. */ - int lookupModes() { + public int lookupModes() { return allowedModes & ALL_MODES; } @@ -621,32 +642,32 @@ public class MethodHandles { /// Helper methods, all package-private. - MemberName resolveOrFail(Class> refc, String name, Class> type, boolean isStatic) { + MemberName resolveOrFail(Class> refc, String name, Class> type, boolean isStatic) throws NoAccessException { checkSymbolicClass(refc); // do this before attempting to resolve int mods = (isStatic ? Modifier.STATIC : 0); return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull()); } - MemberName resolveOrFail(Class> refc, String name, MethodType type, boolean isStatic) { + MemberName resolveOrFail(Class> refc, String name, MethodType type, boolean isStatic) throws NoAccessException { checkSymbolicClass(refc); // do this before attempting to resolve int mods = (isStatic ? Modifier.STATIC : 0); return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull()); } MemberName resolveOrFail(Class> refc, String name, MethodType type, boolean isStatic, - boolean searchSupers, Class> specialCaller) { + boolean searchSupers, Class> specialCaller) throws NoAccessException { checkSymbolicClass(refc); // do this before attempting to resolve int mods = (isStatic ? Modifier.STATIC : 0); return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), searchSupers, specialCaller); } - void checkSymbolicClass(Class> refc) { + void checkSymbolicClass(Class> refc) throws NoAccessException { Class> caller = lookupClassOrNull(); if (caller != null && !VerifyAccess.isClassAccessible(refc, caller)) throw newNoAccessException("symbolic reference class is not public", new MemberName(refc), caller); } - void checkMethod(Class> refc, MemberName m, boolean wantStatic) { + void checkMethod(Class> refc, MemberName m, boolean wantStatic) throws NoAccessException { String message; if (m.isConstructor()) message = "expected a method, not a constructor"; @@ -659,7 +680,7 @@ public class MethodHandles { throw newNoAccessException(message, m, lookupClass()); } - void checkAccess(Class> refc, MemberName m) { + void checkAccess(Class> refc, MemberName m) throws NoAccessException { int allowedModes = this.allowedModes; if (allowedModes == TRUSTED) return; int mods = m.getModifiers(); @@ -695,14 +716,14 @@ public class MethodHandles { return "member is private to package"; } - void checkSpecialCaller(Class> specialCaller) { + void checkSpecialCaller(Class> specialCaller) throws NoAccessException { if (allowedModes == TRUSTED) return; if (!VerifyAccess.isSamePackageMember(specialCaller, lookupClass())) throw newNoAccessException("no private access for invokespecial", new MemberName(specialCaller), lookupClass()); } - MethodHandle restrictProtectedReceiver(MemberName method, MethodHandle mh) { + MethodHandle restrictProtectedReceiver(MemberName method, MethodHandle mh) throws NoAccessException { // The accessing class only has the right to use a protected member // on itself or a subclass. Enforce that restriction, from JVMS 5.4.4, etc. if (!method.isProtected() || method.isStatic() @@ -712,7 +733,7 @@ public class MethodHandles { else return restrictReceiver(method, mh, lookupClass()); } - MethodHandle restrictReceiver(MemberName method, MethodHandle mh, Class> caller) { + MethodHandle restrictReceiver(MemberName method, MethodHandle mh, Class> caller) throws NoAccessException { assert(!method.isStatic()); Class> defc = method.getDeclaringClass(); // receiver type of mh is too wide if (defc.isInterface() || !defc.isAssignableFrom(caller)) { @@ -898,11 +919,16 @@ public class MethodHandles { * @return a method handle which always invokes the call site's target */ public static - MethodHandle dynamicInvoker(CallSite site) { + MethodHandle dynamicInvoker(CallSite site) throws NoAccessException { MethodHandle getCSTarget = GET_TARGET; - if (getCSTarget == null) - GET_TARGET = getCSTarget = Lookup.IMPL_LOOKUP. - findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class)); + if (getCSTarget == null) { + try { + GET_TARGET = getCSTarget = Lookup.IMPL_LOOKUP. + findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class)); + } catch (NoAccessException ex) { + throw new InternalError(); + } + } MethodHandle getTarget = MethodHandleImpl.bindReceiver(IMPL_TOKEN, getCSTarget, site); MethodHandle invoker = exactInvoker(site.type()); return foldArguments(invoker, getTarget); @@ -1260,17 +1286,20 @@ public class MethodHandles { *
* Example: *
- * MethodHandle cat = MethodHandles.lookup().
- * findVirtual(String.class, "concat", String.class, String.class);
- * System.out.println(cat.<String>invokeExact("x", "y")); // xy
+ * import static java.dyn.MethodHandles.*;
+ * import static java.dyn.MethodType.*;
+ * ...
+ * MethodHandle cat = lookup().findVirtual(String.class,
+ * "concat", methodType(String.class, String.class));
+ * System.out.println((String) cat.invokeExact("x", "y")); // xy
* MethodHandle d0 = dropArguments(cat, 0, String.class);
- * System.out.println(d0.<String>invokeExact("x", "y", "z")); // xy
+ * System.out.println((String) d0.invokeExact("x", "y", "z")); // yz
* MethodHandle d1 = dropArguments(cat, 1, String.class);
- * System.out.println(d1.<String>invokeExact("x", "y", "z")); // xz
+ * System.out.println((String) d1.invokeExact("x", "y", "z")); // xz
* MethodHandle d2 = dropArguments(cat, 2, String.class);
- * System.out.println(d2.<String>invokeExact("x", "y", "z")); // yz
- * MethodHandle d12 = dropArguments(cat, 1, String.class, String.class);
- * System.out.println(d12.<String>invokeExact("w", "x", "y", "z")); // wz
+ * System.out.println((String) d2.invokeExact("x", "y", "z")); // xy
+ * MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
+ * System.out.println((String) d12.invokeExact("x", 12, true, "z")); // xz
*
* @param target the method handle to invoke after the argument is dropped
* @param valueTypes the type(s) of the argument to drop
diff --git a/jdk/src/share/classes/java/dyn/MethodType.java b/jdk/src/share/classes/java/dyn/MethodType.java
index c9001bd25a6..e7e948bdb7e 100644
--- a/jdk/src/share/classes/java/dyn/MethodType.java
+++ b/jdk/src/share/classes/java/dyn/MethodType.java
@@ -40,24 +40,37 @@ import static sun.dyn.MemberName.newIllegalArgumentException;
* returned by a method handle, or the arguments and return type passed
* and expected by a method handle caller. Method types must be properly
* matched between a method handle and all its callers,
- * and the JVM's operations enforce this matching at all times.
+ * and the JVM's operations enforce this matching at, specifically
+ * during calls to {@link MethodHandle#invokeExact}
+ * and {@link MethodHandle#invokeGeneric}, and during execution
+ * of {@code invokedynamic} instructions.
* * The structure is a return type accompanied by any number of parameter types. - * The types (primitive, void, and reference) are represented by Class objects. + * The types (primitive, {@code void}, and reference) are represented by {@link Class} objects. + * (For ease of exposition, we treat {@code void} as if it were a type. + * In fact, it denotes the absence of a return type.) *
- * All instances of MethodType are immutable.
+ * All instances of {@code MethodType} are immutable.
* Two instances are completely interchangeable if they compare equal.
* Equality depends on pairwise correspondence of the return and parameter types and on nothing else.
*
* This type can be created only by factory methods. * All factory methods may cache values, though caching is not guaranteed. *
- * Note: Like classes and strings, method types can be represented directly - * as constants to be loaded by {@code ldc} bytecodes. + * {@code MethodType} objects are sometimes derived from bytecode instructions + * such as {@code invokedynamic}, specifically from the type descriptor strings associated + * with the instructions in a class file's constant pool. + * When this occurs, any classes named in the descriptor strings must be loaded. + * (But they need not be initialized.) + * This loading may occur at any time before the {@code MethodType} object is first derived. + *
+ * Like classes and strings, method types can be represented directly + * in a class file's constant pool as constants to be loaded by {@code ldc} bytecodes. + * Loading such a constant causes its component classes to be loaded as necessary. * @author John Rose, JSR 292 EG */ public final -class MethodType { +class MethodType implements java.lang.reflect.Type { private final Class> rtype; private final Class>[] ptypes; private MethodTypeForm form; // erased form, plus cached data about primitives @@ -636,11 +649,11 @@ class MethodType { /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. * Find or create an instance of the given method type. - * Any class or interface name embedded in the signature string + * Any class or interface name embedded in the descriptor string * will be resolved by calling {@link ClassLoader#loadClass(java.lang.String)} * on the given loader (or if it is null, on the system class loader). *
- * Note that it is possible to build method types which cannot be + * Note that it is possible to encounter method types which cannot be * constructed by this method, because their component types are * not all reachable from a common class loader. *
@@ -662,8 +675,11 @@ class MethodType { } /** - * Create a bytecode signature representation of the type. - * Note that this is not a strict inverse of + * Create a bytecode descriptor representation of the method type. + *
+ * Note that this is not a strict inverse of {@link #fromMethodDescriptorString}. + * Two distinct classes which share a common name but have different class loaders + * will appear identical when viewed within descriptor strings. *
* This method is included for the benfit of applications that must
* generate bytecodes that process method handles and invokedynamic.
diff --git a/jdk/src/share/classes/java/dyn/NoAccessException.java b/jdk/src/share/classes/java/dyn/NoAccessException.java
index 5e76f6a4aae..d8a18625401 100644
--- a/jdk/src/share/classes/java/dyn/NoAccessException.java
+++ b/jdk/src/share/classes/java/dyn/NoAccessException.java
@@ -36,7 +36,7 @@ package java.dyn;
* at the time of creation.
* @author John Rose, JSR 292 EG
*/
-public class NoAccessException extends RuntimeException {
+public class NoAccessException extends ReflectiveOperationException {
/**
* Constructs a {@code NoAccessException} with no detail message.
*/
diff --git a/jdk/src/share/classes/sun/dyn/BoundMethodHandle.java b/jdk/src/share/classes/sun/dyn/BoundMethodHandle.java
index 5152187229e..f2ae32efbc9 100644
--- a/jdk/src/share/classes/sun/dyn/BoundMethodHandle.java
+++ b/jdk/src/share/classes/sun/dyn/BoundMethodHandle.java
@@ -48,8 +48,6 @@ public class BoundMethodHandle extends MethodHandle {
private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory(IMPL_TOKEN);
// Constructors in this class *must* be package scoped or private.
- // Exception: JavaMethodHandle constructors are protected.
- // (The link between JMH and BMH is temporary.)
/** Bind a direct MH to its receiver (or first ref. argument).
* The JVM will pre-dispatch the MH if it is not already static.
@@ -122,55 +120,6 @@ public class BoundMethodHandle extends MethodHandle {
assert(this instanceof JavaMethodHandle);
}
- /** Initialize the current object as a Java method handle.
- */
- protected BoundMethodHandle(String entryPointName, MethodType type, boolean matchArity) {
- super(Access.TOKEN, null);
- MethodHandle entryPoint
- = findJavaMethodHandleEntryPoint(this.getClass(),
- entryPointName, type, matchArity);
- MethodHandleImpl.initType(this, entryPoint.type().dropParameterTypes(0, 1));
- this.argument = this; // kludge; get rid of
- this.vmargslot = this.type().parameterSlotDepth(0);
- initTarget(entryPoint, 0);
- assert(this instanceof JavaMethodHandle);
- }
-
- private static
- MethodHandle findJavaMethodHandleEntryPoint(Class> caller,
- String name,
- MethodType type,
- boolean matchArity) {
- if (matchArity) type.getClass(); // elicit NPE
- List
diff --git a/jdk/src/share/classes/sun/dyn/CallSiteImpl.java b/jdk/src/share/classes/sun/dyn/CallSiteImpl.java
index 90d004b6b1a..f7c2d7099a7 100644
--- a/jdk/src/share/classes/sun/dyn/CallSiteImpl.java
+++ b/jdk/src/share/classes/sun/dyn/CallSiteImpl.java
@@ -26,6 +26,7 @@
package sun.dyn;
import java.dyn.*;
+import static sun.dyn.MemberName.uncaughtException;
/**
* Parts of CallSite known to the JVM.
@@ -80,11 +81,18 @@ public class CallSiteImpl {
// This method is private in CallSite because it touches private fields in CallSite.
// These private fields (vmmethod, vmindex) are specific to the JVM.
- private static final MethodHandle PRIVATE_INITIALIZE_CALL_SITE =
+ private static final MethodHandle PRIVATE_INITIALIZE_CALL_SITE;
+ static {
+ try {
+ PRIVATE_INITIALIZE_CALL_SITE =
MethodHandleImpl.IMPL_LOOKUP.findVirtual(CallSite.class, "initializeFromJVM",
MethodType.methodType(void.class,
String.class, MethodType.class,
MemberName.class, int.class));
+ } catch (NoAccessException ex) {
+ throw uncaughtException(ex);
+ }
+ }
public static void setCallSiteTarget(Access token, CallSite site, MethodHandle target) {
Access.check(token);
diff --git a/jdk/src/share/classes/sun/dyn/FilterGeneric.java b/jdk/src/share/classes/sun/dyn/FilterGeneric.java
index 21540e6647e..1e7b594dd93 100644
--- a/jdk/src/share/classes/sun/dyn/FilterGeneric.java
+++ b/jdk/src/share/classes/sun/dyn/FilterGeneric.java
@@ -25,12 +25,8 @@
package sun.dyn;
-import java.dyn.JavaMethodHandle;
-import java.dyn.MethodHandle;
-import java.dyn.MethodType;
-import java.dyn.NoAccessException;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
+import java.dyn.*;
+import java.lang.reflect.*;
import static sun.dyn.MemberName.newIllegalArgumentException;
/**
@@ -119,7 +115,7 @@ class FilterGeneric {
static MethodHandle make(Kind kind, int pos, MethodHandle filter, MethodHandle target) {
FilterGeneric fgen = of(kind, pos, filter.type(), target.type());
- return fgen.makeInstance(kind, pos, filter, target);
+ return fgen.makeInstance(kind, pos, filter, target).asMethodHandle();
}
/** Return the adapter information for this target and filter type. */
diff --git a/jdk/src/share/classes/sun/dyn/FilterOneArgument.java b/jdk/src/share/classes/sun/dyn/FilterOneArgument.java
index 354694f49a4..cc8ecf66d19 100644
--- a/jdk/src/share/classes/sun/dyn/FilterOneArgument.java
+++ b/jdk/src/share/classes/sun/dyn/FilterOneArgument.java
@@ -25,9 +25,8 @@
package sun.dyn;
-import java.dyn.JavaMethodHandle;
-import java.dyn.MethodHandle;
-import java.dyn.MethodType;
+import java.dyn.*;
+import static sun.dyn.MemberName.uncaughtException;
/**
* Unary function composition, useful for many small plumbing jobs.
@@ -51,8 +50,16 @@ public class FilterOneArgument extends JavaMethodHandle {
return target.invokeExact(filteredArgument);
}
- private static final MethodHandle INVOKE =
- MethodHandleImpl.IMPL_LOOKUP.findVirtual(FilterOneArgument.class, "invoke", MethodType.genericMethodType(1));
+ private static final MethodHandle INVOKE;
+ static {
+ try {
+ INVOKE =
+ MethodHandleImpl.IMPL_LOOKUP.findVirtual(FilterOneArgument.class, "invoke",
+ MethodType.genericMethodType(1));
+ } catch (NoAccessException ex) {
+ throw uncaughtException(ex);
+ }
+ }
protected FilterOneArgument(MethodHandle filter, MethodHandle target) {
super(INVOKE);
diff --git a/jdk/src/share/classes/sun/dyn/FromGeneric.java b/jdk/src/share/classes/sun/dyn/FromGeneric.java
index f4a1969f8ff..24f40c0c1ac 100644
--- a/jdk/src/share/classes/sun/dyn/FromGeneric.java
+++ b/jdk/src/share/classes/sun/dyn/FromGeneric.java
@@ -25,15 +25,9 @@
package sun.dyn;
-import java.dyn.JavaMethodHandle;
-import java.dyn.MethodHandle;
-import java.dyn.MethodHandles;
-import java.dyn.MethodType;
-import java.dyn.NoAccessException;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import sun.dyn.util.ValueConversions;
-import sun.dyn.util.Wrapper;
+import java.dyn.*;
+import java.lang.reflect.*;
+import sun.dyn.util.*;
/**
* Adapters which mediate between incoming calls which are generic
diff --git a/jdk/src/share/classes/sun/dyn/Invokers.java b/jdk/src/share/classes/sun/dyn/Invokers.java
index 6af2ac6b171..b3d2823d024 100644
--- a/jdk/src/share/classes/sun/dyn/Invokers.java
+++ b/jdk/src/share/classes/sun/dyn/Invokers.java
@@ -25,10 +25,7 @@
package sun.dyn;
-import java.dyn.MethodHandle;
-import java.dyn.MethodHandles;
-import java.dyn.MethodType;
-
+import java.dyn.*;
/**
* Construction and caching of often-used invokers.
@@ -63,8 +60,11 @@ public class Invokers {
public MethodHandle exactInvoker() {
MethodHandle invoker = exactInvoker;
if (invoker != null) return invoker;
- invoker = MethodHandleImpl.IMPL_LOOKUP.findVirtual(MethodHandle.class, "invoke", targetType);
- if (invoker == null) throw new InternalError("JVM cannot find invoker for "+targetType);
+ try {
+ invoker = MethodHandleImpl.IMPL_LOOKUP.findVirtual(MethodHandle.class, "invoke", targetType);
+ } catch (NoAccessException ex) {
+ throw new InternalError("JVM cannot find invoker for "+targetType);
+ }
assert(invokerType(targetType) == invoker.type());
exactInvoker = invoker;
return invoker;
diff --git a/jdk/src/share/classes/java/dyn/JavaMethodHandle.java b/jdk/src/share/classes/sun/dyn/JavaMethodHandle.java
similarity index 71%
rename from jdk/src/share/classes/java/dyn/JavaMethodHandle.java
rename to jdk/src/share/classes/sun/dyn/JavaMethodHandle.java
index d8cd87a5ed5..2ce44d1d89e 100644
--- a/jdk/src/share/classes/java/dyn/JavaMethodHandle.java
+++ b/jdk/src/share/classes/sun/dyn/JavaMethodHandle.java
@@ -23,8 +23,9 @@
* questions.
*/
-package java.dyn;
+package sun.dyn;
+import java.dyn.*;
import sun.dyn.Access;
/**
@@ -168,70 +169,4 @@ public abstract class JavaMethodHandle
protected JavaMethodHandle(MethodHandle entryPoint) {
super(entryPoint);
}
-
- /**
- * Create a method handle whose entry point is a non-static method
- * visible in the exact (most specific) class of
- * the newly constructed object.
- *
- * The method is specified by name and type, as if via this expression:
- * {@code MethodHandles.lookup().findVirtual(this.getClass(), name, type)}.
- * The class defining the method might be an anonymous inner class.
- *
- * The method handle type of {@code this} (i.e, the fully constructed object)
- * will be the given method handle type.
- * A call to {@code this} will invoke the selected method.
- * The receiver argument will be bound to {@code this} on every method
- * handle invocation.
- *
- * Rationale:
- * Although this constructor may seem to be a mere luxury,
- * it is not subsumed by the more general constructor which
- * takes any {@code MethodHandle} as the entry point argument.
- * In order to convert an entry point name to a method handle,
- * the self-class of the object is required (in order to do
- * the lookup). The self-class, in turn, is generally not
- * available at the time of the constructor invocation,
- * due to the rules of Java and the JVM verifier.
- * One cannot call {@code this.getClass()}, because
- * the value of {@code this} is inaccessible at the point
- * of the constructor call. (Changing this would require
- * change to the Java language, verifiers, and compilers.)
- * In particular, this constructor allows {@code JavaMethodHandle}s
- * to be created in combination with the anonymous inner class syntax.
- * @param entryPointName the name of the entry point method
- * @param type (optional) the desired type of the method handle
- */
- protected JavaMethodHandle(String entryPointName, MethodType type) {
- super(entryPointName, type, true);
-
- }
-
- /**
- * Create a method handle whose entry point is a non-static method
- * visible in the exact (most specific) class of
- * the newly constructed object.
- *
- * The method is specified only by name.
- * There must be exactly one method of that name visible in the object class,
- * either inherited or locally declared.
- * (That is, the method must not be overloaded.)
- *
- * The method handle type of {@code this} (i.e, the fully constructed object)
- * will be the same as the type of the selected non-static method.
- * The receiver argument will be bound to {@code this} on every method
- * handle invocation.
- * ISSUE: This signature wildcarding feature does not correspond to
- * any MethodHandles.Lookup API element. Can we eliminate it?
- * Alternatively, it is useful for naming non-overloaded methods.
- * Shall we make type arguments optional in the Lookup methods,
- * throwing an error in cases of ambiguity?
- *
- * For this method's rationale, see the documentation
- * for {@link #JavaMethodHandle(String,MethodType)}.
- * @param entryPointName the name of the entry point method
- */
- protected JavaMethodHandle(String entryPointName) {
- super(entryPointName, (MethodType) null, false);
- }
}
diff --git a/jdk/src/share/classes/sun/dyn/MemberName.java b/jdk/src/share/classes/sun/dyn/MemberName.java
index db21f2b4121..f45d1603ebf 100644
--- a/jdk/src/share/classes/sun/dyn/MemberName.java
+++ b/jdk/src/share/classes/sun/dyn/MemberName.java
@@ -521,6 +521,11 @@ public final class MemberName implements Member, Cloneable {
if (lookupClass != null) message += ", from " + lookupClass.getName();
return new NoAccessException(message);
}
+ public static Error uncaughtException(Exception ex) {
+ Error err = new InternalError("uncaught exception");
+ err.initCause(ex);
+ return err;
+ }
/** Actually making a query requires an access check. */
public static Factory getFactory(Access token) {
@@ -641,7 +646,7 @@ public final class MemberName implements Member, Cloneable {
* If lookup fails or access is not permitted, a {@linkplain NoAccessException} is thrown.
* Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
*/
- public MemberName resolveOrFail(MemberName m, boolean searchSupers, Class> lookupClass) {
+ public MemberName resolveOrFail(MemberName m, boolean searchSupers, Class> lookupClass) throws NoAccessException {
MemberName result = resolveOrNull(m, searchSupers, lookupClass);
if (result != null)
return result;
diff --git a/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java b/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java
index 25dc470d061..caa96b90d69 100644
--- a/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java
+++ b/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java
@@ -25,11 +25,8 @@
package sun.dyn;
-import java.dyn.JavaMethodHandle;
-import java.dyn.MethodHandle;
-import java.dyn.MethodHandles;
+import java.dyn.*;
import java.dyn.MethodHandles.Lookup;
-import java.dyn.MethodType;
import java.util.logging.Level;
import java.util.logging.Logger;
import sun.dyn.util.VerifyType;
@@ -46,6 +43,7 @@ import sun.dyn.util.Wrapper;
import sun.misc.Unsafe;
import static sun.dyn.MemberName.newIllegalArgumentException;
import static sun.dyn.MemberName.newNoAccessException;
+import static sun.dyn.MemberName.uncaughtException;
/**
* Base class for method handles, containing JVM-specific fields and logic.
@@ -173,7 +171,7 @@ public abstract class MethodHandleImpl {
*/
public static
MethodHandle findMethod(Access token, MemberName method,
- boolean doDispatch, Class> lookupClass) {
+ boolean doDispatch, Class> lookupClass) throws NoAccessException {
Access.check(token); // only trusted calls
MethodType mtype = method.getMethodType();
if (!method.isStatic()) {
@@ -320,7 +318,7 @@ public abstract class MethodHandleImpl {
try {
VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(AllocateObject.class, "invoke_V", MethodType.genericMethodType(0, true));
} catch (NoAccessException ex) {
- throw new InternalError("");
+ throw uncaughtException(ex);
}
}
// Corresponding generic constructor types:
@@ -416,9 +414,7 @@ public abstract class MethodHandleImpl {
f = c.getDeclaredField(field.getName());
return unsafe.staticFieldBase(f);
} catch (Exception ee) {
- Error e = new InternalError();
- e.initCause(ee);
- throw e;
+ throw uncaughtException(ee);
}
}
@@ -473,10 +469,8 @@ public abstract class MethodHandleImpl {
MethodHandle mh;
try {
mh = IMPL_LOOKUP.findVirtual(FieldAccessor.class, name, type);
- } catch (NoAccessException ee) {
- Error e = new InternalError("name,type="+name+type);
- e.initCause(ee);
- throw e;
+ } catch (NoAccessException ex) {
+ throw uncaughtException(ex);
}
if (evclass != vclass || (!isStatic && ecclass != cclass)) {
MethodType strongType = FieldAccessor.ftype(cclass, vclass, isSetter, isStatic);
@@ -543,10 +537,8 @@ public abstract class MethodHandleImpl {
MethodHandle mh;
try {
mh = IMPL_LOOKUP.findStatic(FieldAccessor.class, name, type);
- } catch (NoAccessException ee) {
- Error e = new InternalError("name,type="+name+type);
- e.initCause(ee);
- throw e;
+ } catch (NoAccessException ex) {
+ throw uncaughtException(ex);
}
if (caclass != null) {
MethodType strongType = FieldAccessor.atype(caclass, isSetter);
@@ -1031,7 +1023,7 @@ public abstract class MethodHandleImpl {
try {
VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(GuardWithTest.class, "invoke_V", MethodType.genericMethodType(0, true));
} catch (NoAccessException ex) {
- throw new InternalError("");
+ throw uncaughtException(ex);
}
}
}
@@ -1167,7 +1159,7 @@ public abstract class MethodHandleImpl {
try {
VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(GuardWithCatch.class, "invoke_V", MethodType.genericMethodType(0, true));
} catch (NoAccessException ex) {
- throw new InternalError("");
+ throw uncaughtException(ex);
}
}
}
@@ -1207,9 +1199,16 @@ public abstract class MethodHandleImpl {
return AdapterMethodHandle.makeRetypeRaw(token, type, THROW_EXCEPTION);
}
- static final MethodHandle THROW_EXCEPTION
+ static final MethodHandle THROW_EXCEPTION;
+ static {
+ try {
+ THROW_EXCEPTION
= IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "throwException",
MethodType.methodType(Empty.class, Throwable.class));
+ } catch (NoAccessException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
static