提交 1004768c 编写于 作者: T tbell

Merge

#
# Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved.
# Copyright 2001-2008 Sun Microsystems, Inc. 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
......@@ -55,6 +55,7 @@ EXCLUDE_PKGS = \
# This is a list of regular expressions. So foo.* matches "foo" and "foo.bar".
#
ACTIVE_JSR_PKGS= \
java.dyn \
java.sql \
javax.activation \
javax.annotation.* \
......
#
# Copyright 1995-2006 Sun Microsystems, Inc. All Rights Reserved.
# Copyright 1995-2009 Sun Microsystems, Inc. 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
......@@ -39,7 +39,7 @@ SUBDIRS += hpi version jvm redist verify fdlibm java sun_nio jli main zip
# Others
# Note: java_crw_demo java_hprof_demo are demos but must be delivered built in sdk
SUBDIRS += security npt java_crw_demo java_hprof_demo \
math awt util text applet net nio \
math awt util text applet net nio dyn \
sql rmi jar beans logging management instrument
......
#
# Copyright 2008-2009 Sun Microsystems, Inc. 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. Sun designates this
# particular file as subject to the "Classpath" exception as provided
# by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
# CA 95054 USA or visit www.sun.com if you need additional information or
# have any questions.
#
BUILDDIR = ../..
PACKAGE = java.dyn
PRODUCT = java
include $(BUILDDIR)/common/Defs.gmk
AUTO_FILES_JAVA_DIRS = java/dyn sun/dyn
# The sources built here use new language syntax to generate
# method handle calls. Let's be sure we are using that format.
#LANGUAGE_VERSION = -source 7
#CLASS_VERSION = -target 7
# Actually, it will be less disruptive to compile with the same
# -target option as the rest of the system, and just turn on
# the specific compiler option we need here:
OTHER_JAVACFLAGS = -XDinvokedynamic
include $(BUILDDIR)/common/Classes.gmk
/*
* Copyright 2008-2009 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package java.dyn;
import sun.dyn.util.BytecodeName;
/**
* An <code>invokedynamic</code> call site, as reified to the bootstrap method.
* Every instance of a call site corresponds to a distinct instance
* of the <code>invokedynamic</code> instruction.
* Call sites have state, one reference word, called the <code>target</code>,
* and typed as a {@link MethodHandle}. When this state is null (as it is
* initially) the call site is in the unlinked state. Otherwise, it is said
* to be linked to its target.
* <p>
* When an unlinked call site is executed, a bootstrap routine is called
* to finish the execution of the call site, and optionally to link
* the call site.
* <p>
* @author John Rose, JSR 292 EG
*/
public class CallSite {
// Fields used only by the JVM. Do not use or change.
private Object vmmethod;
int callerMID, callerBCI; // supplied by the JVM
MethodHandle target;
final Object caller; // usually a class
final String name;
final MethodType type;
public CallSite(Object caller, String name, MethodType type) {
this.caller = caller;
this.name = name;
this.type = type;
}
private static void privateInitializeCallSite(CallSite site, int callerMID, int callerBCI) {
site.callerMID = callerMID;
site.callerBCI = callerBCI;
if (site.target == null)
site.setTarget(site.initialTarget());
}
/**
* Just after a call site is created by a bootstrap method handle,
* if the target has not been initialized by the factory method itself,
* the method {@code initialTarget} is called to produce an initial
* non-null target. (Live call sites must never have null targets.)
* <p>
* If the bootstrap method itself does not initialize the call site,
* this method must be overridden, because it just raises an
* {@code InvokeDynamicBootstrapError}.
*/
protected MethodHandle initialTarget() {
throw new InvokeDynamicBootstrapError("target must be initialized before call site is linked: "+this);
}
/**
* Report the current linkage state of the call site. (This is mutable.)
* The value is null if and only if the call site is currently unlinked.
* When a linked call site is invoked, the target method is used directly.
* When an unlinked call site is invoked, its bootstrap method receives
* the call, as if via {@link Linkage#bootstrapInvokeDynamic}.
* <p>
* The interactions of {@code getTarget} with memory are the same
* as of a read from an ordinary variable, such as an array element or a
* non-volatile, non-final field.
* <p>
* In particular, the current thread may choose to reuse the result
* of a previous read of the target from memory, and may fail to see
* a recent update to the target by another thread.
* @return the current linkage state of the call site
* @see #setTarget
*/
public MethodHandle getTarget() {
return target;
}
/**
* Link or relink the call site, by setting its target method.
* <p>
* The interactions of {@code setTarget} with memory are the same
* as of a write to an ordinary variable, such as an array element or a
* non-volatile, non-final field.
* <p>
* In particular, unrelated threads may fail to see the updated target
* until they perform a read from memory.
* Stronger guarantees can be created by putting appropriate operations
* into the bootstrap method and/or the target methods used
* at any given call site.
* @param target the new target, or null if it is to be unlinked
* @throws WrongMethodTypeException if the new target is not null
* and has a method type that differs from the call site's {@link #type}
*/
public void setTarget(MethodHandle target) {
checkTarget(target);
this.target = target;
}
protected void checkTarget(MethodHandle target) {
if (!canSetTarget(target))
throw new WrongMethodTypeException(String.valueOf(target));
}
protected boolean canSetTarget(MethodHandle target) {
return (target != null && target.type() == type());
}
/**
* Report the class containing the call site.
* This is immutable static context.
* @return class containing the call site
*/
public Class<?> callerClass() {
return (Class) caller;
}
/**
* Report the method name specified in the {@code invokedynamic} instruction.
* This is immutable static context.
* <p>
* Note that the name is a JVM bytecode name, and as such can be any
* non-empty string, as long as it does not contain certain "dangerous"
* characters such as slash {@code '/'} and dot {@code '.'}.
* See the Java Virtual Machine specification for more details.
* <p>
* Application such as a language runtimes may need to encode
* arbitrary program element names and other configuration information
* into the name. A standard convention for doing this is
* <a href="http://blogs.sun.com/jrose/entry/symbolic_freedom_in_the_vm">specified here</a>.
* @return method name specified by the call site
*/
public String name() {
return name;
}
/**
* Report the method name specified in the {@code invokedynamic} instruction,
* as a series of components, individually demangled according to
* the standard convention
* <a href="http://blogs.sun.com/jrose/entry/symbolic_freedom_in_the_vm">specified here</a>.
* <p>
* Non-empty runs of characters between dangerous characters are demangled.
* Each component is either a completely arbitrary demangled string,
* or else a character constant for a punctuation character, typically ':'.
* (In principle, the character can be any dangerous character that the
* JVM lets through in a method name, such as '$' or ']'.
* Runtime implementors are encouraged to use colon ':' for building
* structured names.)
* <p>
* In the common case where the name contains no dangerous characters,
* the result is an array whose only element array is the demangled
* name at the call site. Such a demangled name can be any sequence
* of any number of any unicode characters.
* @return method name components specified by the call site
*/
public Object[] nameComponents() {
return BytecodeName.parseBytecodeName(name);
}
/**
* Report the resolved result and parameter types of this call site,
* which are derived from its bytecode-level invocation descriptor.
* The types are packaged into a {@link MethodType}.
* Any linked target of this call site must be exactly this method type.
* This is immutable static context.
* @return method type specified by the call site
*/
public MethodType type() {
return type;
}
@Override
public String toString() {
return "CallSite#"+hashCode()+"["+name+type+" => "+target+"]";
}
}
/*
* Copyright 2008-2009 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package java.dyn;
/**
* Syntactic marker interface to request javac to emit an {@code invokedynamic} instruction.
* <p>
* This type has no particular meaning as a class or interface supertype, and can never be instantiated.
* Logically, it denotes a source of all dynamically typed methods.
* @author John Rose, JSR 292 EG
*/
public final class InvokeDynamic {
private InvokeDynamic() { throw new InternalError(); } // do not instantiate
// no statically defined static methods
}
/*
* Copyright 2008-2009 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package java.dyn;
/**
* Thrown to indicate that an {@code invokedynamic} instruction has
* failed to find its bootstrap method, or the bootstrap method has
* failed to provide a call site with a non-null target.
* <p>
* The boostrap method must have been declared during a class's initialization
* by a call to {@link Linkage#registerBootstrapMethod}.
*
* @author John Rose, JSR 292 EG
*/
public class InvokeDynamicBootstrapError extends LinkageError {
/**
* Constructs a {@code InvokeDynamicBootstrapError} with no detail message.
*/
public InvokeDynamicBootstrapError() {
super();
}
/**
* Constructs a {@code InvokeDynamicBootstrapError} with the specified
* detail message.
*
* @param s the detail message.
*/
public InvokeDynamicBootstrapError(String s) {
super(s);
}
}
/*
* Copyright 2008-2009 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package java.dyn;
/**
* A Java method handle extends the basic method handle type with additional
* programmer defined methods and fields.
* Its behavior as a method handle is determined at instance creation time,
* by providing the new instance with an "entry point" method handle
* to handle calls. This entry point must accept a leading argument
* whose type is the Java method handle itself or a supertype, and the
* entry point is always called with the Java method handle itself as
* the first argument. This is similar to ordinary virtual methods, which also
* accept the receiver object {@code this} as an implicit leading argument.
* The {@code MethodType} of the Java method handle is the same as that
* of the entry point method handle, with the leading parameter type
* omitted.
* <p>
* Here is an example of usage:
* <p><blockquote><pre>
* class Greeter extends JavaMethodHandle {
* public void run() { System.out.println("hello, "+greetee); }
* private final String greetee;
* Greeter(String greetee) {
* super(RUN);
* this.greetee = greetee;
* }
* // the entry point function is computed once:
* private static final MethodHandle RUN
* = MethodHandles.findVirtual(MyMethodHandle.class, "run",
* MethodType.make(void.class));
* }
* Greeter greeter = new Greeter("world");
* greeter.run(); // prints "hello, world"
* MethodHandle mh = greeter;
* mh.invoke(); // also prints "hello, world"
* </pre></blockquote>
* <p>
* In this example, the method {@code run} provides the entry point.
* The entry point need not be a constant value; it may be independently
* computed in each call to the constructor. The entry point does not
* even need to be a method on the Java method handle class, though
* that is the typical case.
* @see MethodHandle
* @author John Rose, JSR 292 EG
*/
public abstract class JavaMethodHandle
// Note: This is an implementation inheritance hack, and will be removed
// with a JVM change which moves the required hidden behavior onto this class.
extends sun.dyn.BoundMethodHandle
{
/**
* When creating a, pass in {@code entryPoint}, any method handle which
* can take the current object
* @param entryPoint
*/
protected JavaMethodHandle(MethodHandle entryPoint) {
super(entryPoint, 0);
}
}
/*
* Copyright 2008-2009 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package java.dyn;
import java.util.WeakHashMap;
import sun.reflect.Reflection;
import static sun.dyn.util.VerifyAccess.checkBootstrapPrivilege;
/**
* Static methods which control the linkage of invokedynamic call sites.
* @author John Rose, JSR 292 EG
*/
public class Linkage {
private Linkage() {} // do not instantiate
/**
* Register a bootstrap method for use for a given caller class.
* The method handle must be of a type equivalent to {@link Linkage#makeCallSite}.
* <p>
* The operation will fail with an exception if any of the following conditions hold:
* <ul>
* <li>The caller of this method is in a different package than the {@code callerClass},
* and there is a security manager, and its {@code checkPermission} call throws
* when passed {@link LinkagePermission}("registerBootstrapMethod",callerClass).
* <li>The given class already has a bootstrap method, either from an embedded
* {@code BootstrapInvokeDynamic} classfile attribute, or from a previous
* call to this method.
* <li>The given class is already fully initialized.
* <li>The given class is in the process of initialization, in another thread.
* </ul>
* Because of these rules, a class may install its own bootstrap method in
* a static initializer.
*/
public static
void registerBootstrapMethod(Class callerClass, MethodHandle mh) {
Class callc = Reflection.getCallerClass(2);
checkBootstrapPrivilege(callc, callerClass, "registerBootstrapMethod");
checkBSM(mh);
synchronized (bootstrapMethods) {
if (bootstrapMethods.containsKey(callerClass))
throw new IllegalStateException("bootstrap method already declared in "+callerClass);
bootstrapMethods.put(callerClass, mh);
}
}
static void checkBSM(MethodHandle mh) {
if (mh == null) throw new IllegalArgumentException("null bootstrap method");
if (mh.type() == OLD_BOOTSTRAP_METHOD_TYPE) // FIXME: delete at EDR/PFD
throw new WrongMethodTypeException("bootstrap method must be a CallSite factory");
if (mh.type() != BOOTSTRAP_METHOD_TYPE)
throw new WrongMethodTypeException(mh.toString());
}
/**
* Simplified version of registerBootstrapMethod for self-registration,
* to be called from a static initializer.
* Finds a static method of type (CallSite, Object[]) -> Object in the
* given class, and installs it on the caller.
* @throws IllegalArgumentException if there is no such method
*/
public static
void registerBootstrapMethod(Class<?> runtime, String name) {
Class callc = Reflection.getCallerClass(2);
MethodHandle bootstrapMethod =
MethodHandles.findStaticFrom(callc, runtime, name, BOOTSTRAP_METHOD_TYPE);
// FIXME: exception processing wrong here
checkBSM(bootstrapMethod);
Linkage.registerBootstrapMethod(callc, bootstrapMethod);
}
/**
* Simplified version of registerBootstrapMethod for self-registration,
* to be called from a static initializer.
* Finds a static method of type (CallSite, Object[]) -> Object in the
* caller's class, and installs it on the caller.
* @throws IllegalArgumentException if there is no such method
*/
public static
void registerBootstrapMethod(String name) {
Class callc = Reflection.getCallerClass(2);
MethodHandle bootstrapMethod =
MethodHandles.findStaticFrom(callc, callc, name, BOOTSTRAP_METHOD_TYPE);
// FIXME: exception processing wrong here
checkBSM(bootstrapMethod);
Linkage.registerBootstrapMethod(callc, bootstrapMethod);
}
/**
* Report the bootstrap method registered for a given class.
* Returns null if the class has never yet registered a bootstrap method,
* or if the class has explicitly registered a null bootstrap method.
* Only callers privileged to set the bootstrap method may inquire
* about it, because a bootstrap method is potentially a back-door entry
* point into its class.
*/
public static
MethodHandle getBootstrapMethod(Class callerClass) {
Class callc = Reflection.getCallerClass(2);
checkBootstrapPrivilege(callc, callerClass, "registerBootstrapMethod");
synchronized (bootstrapMethods) {
return bootstrapMethods.get(callerClass);
}
}
/** The type of any bootstrap method is a three-argument method
* {@code (Class<?>, String, MethodType)} returning a {@code CallSite}.
*/
public static final MethodType BOOTSTRAP_METHOD_TYPE
= MethodType.make(CallSite.class,
Class.class, String.class, MethodType.class);
private static final MethodType OLD_BOOTSTRAP_METHOD_TYPE
= MethodType.make(Object.class,
CallSite.class, Object[].class);
private static final WeakHashMap<Class, MethodHandle> bootstrapMethods =
new WeakHashMap<Class, MethodHandle>();
/**
* Invalidate all <code>invokedynamic</code> call sites everywhere.
* <p>
* When this method returns, every <code>invokedynamic</code> instruction
* will invoke its bootstrap method on next call.
* <p>
* It is unspecified whether call sites already known to the Java
* code will continue to be associated with <code>invokedynamic</code>
* instructions. If any call site is still so associated, its
* {@link CallSite#getTarget()} method is guaranteed to return null
* the invalidation operation completes.
* <p>
* Invalidation operations are likely to be slow. Use them sparingly.
*/
public static
Object invalidateAll() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkPermission(new LinkagePermission("invalidateAll"));
}
throw new UnsupportedOperationException("NYI");
}
/**
* Invalidate all <code>invokedynamic</code> call sites associated
* with the given class.
* (These are exactly those sites which report the given class
* via the {@link CallSite#callerClass()} method.)
* <p>
* When this method returns, every matching <code>invokedynamic</code>
* instruction will invoke its bootstrap method on next call.
* <p>
* For additional semantics of call site invalidation,
* see {@link #invalidateAll()}.
*/
public static
Object invalidateCallerClass(Class<?> callerClass) {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkPermission(new LinkagePermission("invalidateAll", callerClass));
}
throw new UnsupportedOperationException("NYI");
}
private static Object doNotBootstrap(CallSite site, Object... arguments) {
throw new UnsupportedOperationException("call site must not have null target: "+site);
}
private static final MethodHandle DO_NOT_BOOTSTRAP =
MethodHandles.Lookup.IMPL_LOOKUP.findStatic(Linkage.class, "doNotBootstrap",
OLD_BOOTSTRAP_METHOD_TYPE);
// Up-call from the JVM. Obsolete. FIXME: Delete from VM then from here.
static
MethodHandle findBootstrapMethod(Class callerClass, Class searchBootstrapClass) {
return DO_NOT_BOOTSTRAP;
}
}
/*
* Copyright 2008-2009 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package java.dyn;
import java.security.*;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.StringTokenizer;
/**
* This class is for runtime permissions. A RuntimePermission
* contains a name (also referred to as a "target name") but
* no actions list; you either have the named permission
* or you don't.
*
* <P>
* The target name is the name of the runtime permission (see below). The
* naming convention follows the hierarchical property naming convention.
* Also, an asterisk
* may appear at the end of the name, following a ".", or by itself, to
* signify a wildcard match. For example: "loadLibrary.*" or "*" is valid,
* "*loadLibrary" or "a*b" is not valid.
* <P>
* 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.
* <P>
*
* <table border=1 cellpadding=5 summary="permission target name,
* what the target allows,and associated risks">
* <tr>
* <th>Permission Target Name</th>
* <th>What the Permission Allows</th>
* <th>Risks of Allowing this Permission</th>
* </tr>
*
* <tr>
* <td>registerBootstrapMethod.{class name}</td>
* <td>Specifying a bootstrap method for invokedynamic, within a class of the given name</td>
* <td>An attacker could attempt to attach a bootstrap method to a class which
* has just been loaded, thus gaining control of its invokedynamic calls.</td>
* </tr>
*
* <tr>
* <td>invalidateAll</td>
* <td>Force the relinking of invokedynamic call sites everywhere.</td>
* <td>This could allow an attacker to slow down the system, or perhaps surface timing bugs in a dynamic language implementations, by forcing redundant relinking operations.</td>
* </tr>
*
*
* <tr>
* <td>invalidateCallerClass.{class name}</td>
* <td>Force the relinking of invokedynamic call sites in the given class.</td>
* <td>See {@code invalidateAll}.</td>
* </tr>
* </table>
*
* @see java.security.BasicPermission
* @see java.lang.SecurityManager
*
* @author John Rose, JSR 292 EG
*/
public final class LinkagePermission extends BasicPermission {
/**
* Create a new LinkagePermission with the given name.
* The name is the symbolic name of the LinkagePermission, such as
* "registerBootstrapMethod", "invalidateClass.*", etc. An asterisk
* may appear at the end of the name, following a ".", or by itself, to
* signify a wildcard match.
*
* @param name the name of the LinkagePermission
*/
public LinkagePermission(String name) {
super(name);
}
/**
* Create a new LinkagePermission with the given name on the given class.
* Equivalent to {@code LinkagePermission(name+"."+clazz.getName())}.
*
* @param name the name of the LinkagePermission
* @param clazz the class affected by the permission
*/
public LinkagePermission(String name, Class<?> clazz) {
super(name + "." + clazz.getName());
}
}
/*
* Copyright 2008-2009 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package java.dyn;
//import sun.dyn.*;
import sun.dyn.Access;
import sun.dyn.MethodHandleImpl;
/**
* A method handle is a typed reference to the entry point of a method.
* <p>
* Method handles are strongly typed according to signature.
* They are not distinguished by method name or enclosing class.
* A method handle must be invoked under a signature which exactly matches
* the method handle's own type.
* <p>
* Every method handle confesses its type via the <code>type</code> accessor.
* The structure of this type is a series of classes, one of which is
* the return type of the method (or <code>void.class</code> if none).
* <p>
* Every method handle appears as an object containing a method named
* <code>invoke</code>, whose signature exactly matches
* the method handle's type.
* A normal Java method call (using the <code>invokevirtual</code> instruction)
* can invoke this method from Java source code (if language support is present).
* <p>
* Every call to a method handle specifies an intended method type,
* which must exactly match the type of the method handle.
* (The type is specified in the <code>invokevirtual</code> instruction,
* via a {@code CONSTANT_NameAndType} constant pool entry.)
* The call looks within the receiver object for a method
* named <code>invoke</code> of the intended method type.
* The call fails with a {@link WrongMethodTypeException}
* if the method does not exist, even if there is an <code>invoke</code>
* method of a closely similar signature.
* <p>
* A method handle is an unrestricted capability to call a method.
* A method handle can be formed on a non-public method by a class
* that has access to that method; the resulting handle can be used
* in any place by any caller who receives a reference to it. Thus, access
* checking is performed when the method handle is created, not
* (as in reflection) every time it is called. Handles to non-public
* methods, or in non-public classes, should generally be kept secret.
* They should not be passed to untrusted code.
* <p>
* Bytecode in an extended JVM can directly call a method handle's
* <code>invoke</code> from an <code>invokevirtual</code> instruction.
* The receiver class type must be <code>MethodHandle</code> and the method name
* must be <code>invoke</code>. The signature of the invocation
* (after resolving symbolic type names) must exactly match the method type
* of the target method.
* <p>
* Bytecode in an extended JVM can directly obtain a method handle
* for any accessible method from a <code>ldc</code> instruction
* which refers to a <code>CONSTANT_Methodref</code> or
* <code>CONSTANT_InterfaceMethodref</code> constant pool entry.
* <p>
* All JVMs can also use a reflective API called <code>MethodHandles</code>
* for creating and calling method handles.
* <p>
* A method reference may refer either to a static or non-static method.
* In the non-static case, the method handle type includes an explicit
* receiver argument, prepended before any other arguments.
* In the method handle's type, the initial receiver argument is typed
* according to the class under which the method was initially requested.
* (E.g., if a non-static method handle is obtained via <code>ldc</code>,
* the type of the receiver is the class named in the constant pool entry.)
* <p>
* When a method handle to a virtual method is invoked, the method is
* always looked up in the receiver (that is, the first argument).
* <p>
* A non-virtual method handles to a specific virtual method implementation
* can also be created. These do not perform virtual lookup based on
* receiver type. Such a method handle simulates the effect of
* an <code>invokespecial</code> instruction to the same method.
*
* @see MethodType
* @see MethodHandles
* @author John Rose, JSR 292 EG
*/
public abstract class MethodHandle
// Note: This is an implementation inheritance hack, and will be removed
// with a JVM change which moves the required hidden state onto this class.
extends MethodHandleImpl
{
// interface MethodHandle<T extends MethodType<R,A...>>
// { T type(); <R,A...> public R invoke(A...); }
final private MethodType type;
/**
* Report the type of this method handle.
* Every invocation of this method handle must exactly match this type.
* @return the method handle type
*/
public MethodType type() {
return type;
}
/**
* The constructor for MethodHandle may only be called by privileged code.
* Subclasses may be in other packages, but must possess
* a token which they obtained from MH with a security check.
* @param token non-null object which proves access permission
* @param type type (permanently assigned) of the new method handle
*/
protected MethodHandle(Access token, MethodType type) {
super(token);
this.type = type;
}
}
此差异已折叠。
此差异已折叠。
/*
* Copyright 2008-2009 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package java.dyn;
/**
* TO DO: Temporary shim; remove after refactoring effects are complete in JVM.
* @author John Rose
*/
import sun.dyn.MethodTypeImpl;
class MethodTypeForm extends MethodTypeImpl {
MethodTypeForm(MethodType erasedType) {
super(erasedType);
}
}
/*
* Copyright 2008-2009 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package java.dyn;
/**
* Thrown to indicate that a caller has attempted to create a method handle
* which calls a method to which the caller does not have access.
* This unchecked exception is analogous to {@link IllegalAccessException},
* which is a checked exception thrown when reflective invocation fails
* because of an access check. With method handles, this same access
* checking is performed on behalf of the method handle creator,
* at the time of creation.
* @author John Rose, JSR 292 EG
*/
public class NoAccessException extends RuntimeException {
/**
* Constructs a {@code NoAccessException} with no detail message.
*/
public NoAccessException() {
super();
}
/**
* Constructs a {@code NoAccessException} with the specified
* detail message.
*
* @param s the detail message
*/
public NoAccessException(String s) {
super(s);
}
/**
* Constructs a {@code NoAccessException} with the specified cause.
*
* @param cause the underlying cause of the exception
*/
public NoAccessException(Throwable cause) {
super(cause);
}
/**
* Constructs a {@code NoAccessException} with the specified
* detail message and cause.
*
* @param s the detail message
* @param cause the underlying cause of the exception
*/
public NoAccessException(String s, Throwable cause) {
super(s, cause);
}
}
/*
* Copyright 2008-2009 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package java.dyn;
/**
* Thrown to indicate that code has attempted to call a method handle
* via the wrong method type. As with the bytecode representation of
* normal Java method calls, method handle calls are strongly typed
* to a specific signature associated with a call site.
* <p>
* This exception may also be thrown when two method handles are
* composed, and the system detects that their types cannot be
* matched up correctly. This amounts to an early evaluation
* of the type mismatch, at method handle construction time,
* instead of when the mismatched method handle is called.
*
* @author John Rose, JSR 292 EG
*/
public class WrongMethodTypeException extends RuntimeException {
/**
* Constructs a {@code WrongMethodTypeException} with no detail message.
*/
public WrongMethodTypeException() {
super();
}
/**
* Constructs a {@code WrongMethodTypeException} with the specified
* detail message.
*
* @param s the detail message.
*/
public WrongMethodTypeException(String s) {
super(s);
}
}
/*
* Copyright 2008-2009 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/**
* This package contains dynamic language support provided directly by
* the Java core class libraries and virtual machine.
* @author John Rose, JSR 292 EG
*/
package java.dyn;
......@@ -503,20 +503,25 @@ public final class Console implements Flushable
// Set up JavaIOAccess in SharedSecrets
static {
// Add a shutdown hook to restore console's echo state should
// it be necessary.
sun.misc.SharedSecrets.getJavaLangAccess()
.registerShutdownHook(0 /* shutdown hook invocation order */,
new Runnable() {
public void run() {
try {
if (echoOff) {
echo(true);
}
} catch (IOException x) { }
}
});
try {
// Add a shutdown hook to restore console's echo state should
// it be necessary.
sun.misc.SharedSecrets.getJavaLangAccess()
.registerShutdownHook(0 /* shutdown hook invocation order */,
false /* only register if shutdown is not in progress */,
new Runnable() {
public void run() {
try {
if (echoOff) {
echo(true);
}
} catch (IOException x) { }
}
});
} catch (IllegalStateException e) {
// shutdown is already in progress and console is first used
// by a shutdown hook
}
sun.misc.SharedSecrets.setJavaIOAccess(new sun.misc.JavaIOAccess() {
public Console console() {
......
......@@ -34,23 +34,31 @@ import java.io.File;
*/
class DeleteOnExitHook {
private static LinkedHashSet<String> files = new LinkedHashSet<String>();
static {
sun.misc.SharedSecrets.getJavaLangAccess()
.registerShutdownHook(2 /* Shutdown hook invocation order */,
new Runnable() {
public void run() {
runHooks();
}
});
// DeleteOnExitHook must be the last shutdown hook to be invoked.
// Application shutdown hooks may add the first file to the
// delete on exit list and cause the DeleteOnExitHook to be
// registered during shutdown in progress. So set the
// registerShutdownInProgress parameter to true.
sun.misc.SharedSecrets.getJavaLangAccess()
.registerShutdownHook(2 /* Shutdown hook invocation order */,
true /* register even if shutdown in progress */,
new Runnable() {
public void run() {
runHooks();
}
}
);
}
private static LinkedHashSet<String> files = new LinkedHashSet<String>();
private DeleteOnExitHook() {}
static synchronized void add(String file) {
if(files == null)
if(files == null) {
// DeleteOnExitHook is running. Too late to add a file
throw new IllegalStateException("Shutdown in progress");
}
files.add(file);
}
......
......@@ -35,17 +35,26 @@ import java.util.*;
*/
class ApplicationShutdownHooks {
/* The set of registered hooks */
private static IdentityHashMap<Thread, Thread> hooks;
static {
Shutdown.add(1 /* shutdown hook invocation order */,
new Runnable() {
public void run() {
runHooks();
try {
Shutdown.add(1 /* shutdown hook invocation order */,
false /* not registered if shutdown in progress */,
new Runnable() {
public void run() {
runHooks();
}
}
});
);
hooks = new IdentityHashMap<Thread, Thread>();
} catch (IllegalStateException e) {
// application shutdown hooks cannot be added if
// shutdown is in progress.
hooks = null;
}
}
/* The set of registered hooks */
private static IdentityHashMap<Thread, Thread> hooks = new IdentityHashMap<Thread, Thread>();
private ApplicationShutdownHooks() {}
......
......@@ -53,6 +53,9 @@ class Shutdown {
private static final int MAX_SYSTEM_HOOKS = 10;
private static final Runnable[] hooks = new Runnable[MAX_SYSTEM_HOOKS];
// the index of the currently running shutdown hook to the hooks array
private static int currentRunningHook = 0;
/* The preceding static fields are protected by this lock */
private static class Lock { };
private static Object lock = new Lock();
......@@ -68,17 +71,39 @@ class Shutdown {
}
/* Add a new shutdown hook. Checks the shutdown state and the hook itself,
/**
* Add a new shutdown hook. Checks the shutdown state and the hook itself,
* but does not do any security checks.
*
* The registerShutdownInProgress parameter should be false except
* registering the DeleteOnExitHook since the first file may
* be added to the delete on exit list by the application shutdown
* hooks.
*
* @params slot the slot in the shutdown hook array, whose element
* will be invoked in order during shutdown
* @params registerShutdownInProgress true to allow the hook
* to be registered even if the shutdown is in progress.
* @params hook the hook to be registered
*
* @throw IllegalStateException
* if registerShutdownInProgress is false and shutdown is in progress; or
* if registerShutdownInProgress is true and the shutdown process
* already passes the given slot
*/
static void add(int slot, Runnable hook) {
static void add(int slot, boolean registerShutdownInProgress, Runnable hook) {
synchronized (lock) {
if (state > RUNNING)
throw new IllegalStateException("Shutdown in progress");
if (hooks[slot] != null)
throw new InternalError("Shutdown hook at slot " + slot + " already registered");
if (!registerShutdownInProgress) {
if (state > RUNNING)
throw new IllegalStateException("Shutdown in progress");
} else {
if (state > HOOKS || (state == HOOKS && slot <= currentRunningHook))
throw new IllegalStateException("Shutdown in progress");
}
hooks[slot] = hook;
}
}
......@@ -86,11 +111,15 @@ class Shutdown {
/* Run all registered shutdown hooks
*/
private static void runHooks() {
/* We needn't bother acquiring the lock just to read the hooks field,
* since the hooks can't be modified once shutdown is in progress
*/
for (Runnable hook : hooks) {
for (int i=0; i < MAX_SYSTEM_HOOKS; i++) {
try {
Runnable hook;
synchronized (lock) {
// acquire the lock to make sure the hook registered during
// shutdown is visible here.
currentRunningHook = i;
hook = hooks[i];
}
if (hook != null) hook.run();
} catch(Throwable t) {
if (t instanceof ThreadDeath) {
......
......@@ -1171,8 +1171,8 @@ public final class System {
public void blockedOn(Thread t, Interruptible b) {
t.blockedOn(b);
}
public void registerShutdownHook(int slot, Runnable r) {
Shutdown.add(slot, r);
public void registerShutdownHook(int slot, boolean registerShutdownInProgress, Runnable hook) {
Shutdown.add(slot, registerShutdownInProgress, hook);
}
});
}
......
......@@ -154,7 +154,7 @@ class ZipFile implements ZipConstants {
* @param file the ZIP file to be opened for reading
* @param mode the mode in which the file is to be opened
* @param charset
* the {@link java.nio.charset.Charset {@code charset}} to
* the {@linkplain java.nio.charset.Charset charset} to
* be used to decode the ZIP entry name and comment that are not
* encoded by using UTF-8 encoding (indicated by entry's general
* purpose flag).
......@@ -206,7 +206,7 @@ class ZipFile implements ZipConstants {
*
* @param name the name of the zip file
* @param charset
* the {@link java.nio.charset.Charset {@code charset}} to
* the {@linkplain java.nio.charset.Charset charset} to
* be used to decode the ZIP entry name and comment that are not
* encoded by using UTF-8 encoding (indicated by entry's general
* purpose flag).
......@@ -230,7 +230,7 @@ class ZipFile implements ZipConstants {
* Opens a ZIP file for reading given the specified File object.
* @param file the ZIP file to be opened for reading
* @param charset
* The {@link java.nio.charset.Charset {@code charset}} to be
* The {@linkplain java.nio.charset.Charset charset} to be
* used to decode the ZIP entry name and comment (ignored if
* the <a href="package-summary.html#lang_encoding"> language
* encoding bit</a> of the ZIP entry's general purpose bit
......
......@@ -84,7 +84,7 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
* @param in the actual input stream
*
* @param charset
* The {@link java.nio.charset.Charset {@code charset}} to be
* The {@linkplain java.nio.charset.Charset charset} to be
* used to decode the ZIP entry name (ignored if the
* <a href="package-summary.html#lang_encoding"> language
* encoding bit</a> of the ZIP entry's general purpose bit
......
......@@ -108,7 +108,7 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
*
* @param out the actual output stream
*
* @param charset the {@link java.nio.charset.Charset </code>charset<code>}
* @param charset the {@linkplain java.nio.charset.Charset charset}
* to be used to encode the entry names and comments
*
* @since 1.7
......
/*
* Copyright 2008-2009 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package sun.dyn;
import sun.reflect.Reflection;
/**
* Access control to this package.
* Classes in other packages can attempt to acquire the access token,
* but will fail if they are not recognized as friends.
* Certain methods in this package, although public, require a non-null
* access token in order to proceed; they act like package-private methods.
* @author jrose
*/
public class Access {
private Access() { }
/**
* The heart of this pattern: The list of classes which are
* permitted to acquire the access token, and become honorary
* members of this package.
*/
private static final String[] FRIENDS = {
"java.dyn.", "sun.dyn."
};
/**
* The following object is NOT public. That's the point of the pattern.
* It is package-private, so that any member of this package
* can acquire the access token, and give it away to trusted friends.
*/
static final Access TOKEN = new Access();
/**
* @return Access.TOKEN, if the caller is a friend of this package
*/
public static Access getToken() {
Class<?> callc = Reflection.getCallerClass(2);
if (isFriend(callc))
return TOKEN;
else
throw new IllegalAccessError("bad caller: " + callc);
}
/** Is the given name the name of a class which could be our friend? */
public static boolean isFriendName(String name) {
for (String friend : FRIENDS) {
if (name.startsWith(friend))
return true;
}
return false;
}
/** Is the given class a friend? True if {@link #isFriendName},
* and the given class also shares a class loader with us.
*/
public static boolean isFriend(Class<?> c) {
return isFriendName(c.getName()) && c.getClassLoader() == CLASS_LOADER;
}
private static final ClassLoader CLASS_LOADER = Access.class.getClassLoader();
/**
* Throw an IllegalAccessError if the caller does not possess
* the Access.TOKEN.
* @param must be Access.TOKEN
*/
public static void check(Access token) {
if (token == null)
fail();
// else it must be the unique Access.TOKEN
assert(token == Access.TOKEN);
}
private static void fail() {
final int CALLER_DEPTH = 3;
// 0: Reflection.getCC, 1: this.fail, 2: Access.*, 3: caller
Class<?> callc = Reflection.getCallerClass(CALLER_DEPTH);
throw new IllegalAccessError("bad caller: " + callc);
}
static {
//sun.reflect.Reflection.registerMethodsToFilter(MH.class, "getToken");
}
}
此差异已折叠。
/*
* Copyright 2008-2009 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package sun.dyn;
import sun.dyn.util.VerifyType;
import sun.dyn.util.Wrapper;
import java.dyn.*;
/**
* The flavor of method handle which emulates an invoke instruction
* on a predetermined argument. The JVM dispatches to the correct method
* when the handle is created, not when it is invoked.
* @author jrose
*/
public class BoundMethodHandle extends MethodHandle {
//MethodHandle vmtarget; // next BMH or final DMH or methodOop
private final Object argument; // argument to insert
private final int vmargslot; // position at which it is inserted
// Constructors in this class *must* be package scoped or private.
/** Bind a direct MH to its receiver (or first ref. argument).
* The JVM will pre-dispatch the MH if it is not already static.
*/
BoundMethodHandle(DirectMethodHandle mh, Object argument) {
super(Access.TOKEN, mh.type().dropParameterType(0));
// check the type now, once for all:
this.argument = checkReferenceArgument(argument, mh, 0);
this.vmargslot = this.type().parameterSlotCount();
if (MethodHandleNatives.JVM_SUPPORT) {
this.vmtarget = null; // maybe updated by JVM
MethodHandleNatives.init(this, mh, 0);
} else {
this.vmtarget = mh;
}
}
private static final int REF_ARG = 0, PRIM_ARG = 1, SELF_ARG = 2;
/** Insert an argument into an arbitrary method handle.
* If argnum is zero, inserts the first argument, etc.
* The argument type must be a reference.
*/
BoundMethodHandle(MethodHandle mh, Object argument, int argnum) {
this(mh, argument, argnum, mh.type().parameterType(argnum).isPrimitive() ? PRIM_ARG : REF_ARG);
}
/** Insert an argument into an arbitrary method handle.
* If argnum is zero, inserts the first argument, etc.
*/
BoundMethodHandle(MethodHandle mh, Object argument, int argnum, int whichArg) {
super(Access.TOKEN, mh.type().dropParameterType(argnum));
if (whichArg == PRIM_ARG)
this.argument = bindPrimitiveArgument(argument, mh, argnum);
else {
if (whichArg == SELF_ARG) argument = this;
this.argument = checkReferenceArgument(argument, mh, argnum);
}
this.vmargslot = this.type().parameterSlotDepth(argnum);
if (MethodHandleNatives.JVM_SUPPORT) {
this.vmtarget = null; // maybe updated by JVM
MethodHandleNatives.init(this, mh, argnum);
} else {
this.vmtarget = mh;
}
}
/** For the AdapterMethodHandle subclass.
*/
BoundMethodHandle(MethodType type, Object argument, int vmargslot) {
super(Access.TOKEN, type);
this.argument = argument;
this.vmargslot = vmargslot;
assert(this.getClass() == AdapterMethodHandle.class);
}
/** Initialize the current object as a method handle, binding it
* as the {@code argnum}th argument of the method handle {@code entryPoint}.
* The invocation type of the resulting method handle will be the
* same as {@code entryPoint}, except that the {@code argnum}th argument
* type will be dropped.
*/
public BoundMethodHandle(MethodHandle entryPoint, int argnum) {
this(entryPoint, null, argnum, SELF_ARG);
// Note: If the conversion fails, perhaps because of a bad entryPoint,
// the MethodHandle.type field will not be filled in, and therefore
// no MH.invoke call will ever succeed. The caller may retain a pointer
// to the broken method handle, but no harm can be done with it.
}
/** Initialize the current object as a method handle, binding it
* as the first argument of the method handle {@code entryPoint}.
* The invocation type of the resulting method handle will be the
* same as {@code entryPoint}, except that the first argument
* type will be dropped.
*/
public BoundMethodHandle(MethodHandle entryPoint) {
this(entryPoint, null, 0, SELF_ARG);
}
/** Make sure the given {@code argument} can be used as {@code argnum}-th
* parameter of the given method handle {@code mh}, which must be a reference.
* <p>
* If this fails, throw a suitable {@code WrongMethodTypeException},
* which will prevent the creation of an illegally typed bound
* method handle.
*/
final static Object checkReferenceArgument(Object argument, MethodHandle mh, int argnum) {
Class<?> ptype = mh.type().parameterType(argnum);
if (ptype.isPrimitive()) {
// fail
} else if (argument == null) {
return null;
} else if (VerifyType.isNullReferenceConversion(argument.getClass(), ptype)) {
return argument;
}
throw badBoundArgumentException(argument, mh, argnum);
}
/** Make sure the given {@code argument} can be used as {@code argnum}-th
* parameter of the given method handle {@code mh}, which must be a primitive.
* <p>
* If this fails, throw a suitable {@code WrongMethodTypeException},
* which will prevent the creation of an illegally typed bound
* method handle.
*/
final static Object bindPrimitiveArgument(Object argument, MethodHandle mh, int argnum) {
Class<?> ptype = mh.type().parameterType(argnum);
Wrapper wrap = Wrapper.forPrimitiveType(ptype);
Object zero = wrap.zero();
if (zero == null) {
// fail
} else if (argument == null) {
if (ptype != int.class && wrap.isSubwordOrInt())
return Integer.valueOf(0);
else
return zero;
} else if (VerifyType.isNullReferenceConversion(argument.getClass(), zero.getClass())) {
if (ptype != int.class && wrap.isSubwordOrInt())
return Wrapper.INT.wrap(argument);
else
return argument;
}
throw badBoundArgumentException(argument, mh, argnum);
}
final static RuntimeException badBoundArgumentException(Object argument, MethodHandle mh, int argnum) {
String atype = (argument == null) ? "null" : argument.getClass().toString();
return new WrongMethodTypeException("cannot bind "+atype+" argument to parameter #"+argnum+" of "+mh.type());
}
@Override
public String toString() {
return "Bound[" + super.toString() + "]";
}
}
/*
* Copyright 2008-2009 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package sun.dyn;
import java.dyn.*;
/**
* The CallSite privately created by the JVM at every invokedynamic instruction.
* @author jrose
*/
class CallSiteImpl extends CallSite {
// Fields used only by the JVM. Do not use or change.
private Object vmmethod;
// Values supplied by the JVM:
int callerMID, callerBCI;
private CallSiteImpl(Class<?> caller, String name, MethodType type) {
super(caller, name, type);
}
@Override
public void setTarget(MethodHandle mh) {
checkTarget(mh);
if (MethodHandleNatives.JVM_SUPPORT)
MethodHandleNatives.linkCallSite(this, (MethodHandle) mh);
else
super.setTarget(mh);
}
private static final MethodHandle PRIVATE_INITIALIZE_CALL_SITE =
MethodHandleImpl.IMPL_LOOKUP.findStatic(CallSite.class, "privateInitializeCallSite",
MethodType.make(void.class, CallSite.class, int.class, int.class));
// this is the up-call from the JVM:
static CallSite makeSite(Class<?> caller, String name, MethodType type,
int callerMID, int callerBCI) {
MethodHandle bsm = Linkage.getBootstrapMethod(caller);
if (bsm == null)
throw new InvokeDynamicBootstrapError("class has no bootstrap method: "+caller);
CallSite site = bsm.<CallSite>invoke(caller, name, type);
if (site == null)
throw new InvokeDynamicBootstrapError("class bootstrap method failed to create a call site: "+caller);
PRIVATE_INITIALIZE_CALL_SITE.<void>invoke(site, callerMID, callerBCI);
return site;
}
}
/*
* Copyright 2008-2009 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package sun.dyn;
import java.dyn.*;
import static sun.dyn.MethodHandleNatives.Constants.*;
/**
* The flavor of method handle which emulates invokespecial or invokestatic.
* @author jrose
*/
class DirectMethodHandle extends MethodHandle {
//inherited oop vmtarget; // methodOop or virtual class/interface oop
private final int vmindex; // method index within class or interface
{ vmindex = VM_INDEX_UNINITIALIZED; } // JVM may change this
// Constructors in this class *must* be package scoped or private.
DirectMethodHandle(MethodType mtype, MemberName m, boolean doDispatch, Class<?> lookupClass) {
super(Access.TOKEN, mtype);
assert(m.isMethod() || !doDispatch && m.isConstructor());
if (!m.isResolved())
throw new InternalError();
// Null check and replace privilege token (as passed to JVM) with null.
if (lookupClass.equals(Access.class)) lookupClass = null;
MethodHandleNatives.init(this, (Object) m, doDispatch, lookupClass);
}
boolean isValid() {
return (vmindex != VM_INDEX_UNINITIALIZED);
}
}
/*
* Copyright 2008-2009 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sf, tifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
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;
/**
* "Flyby adapters" which apply arbitrary conversions to arguments
* on the way to a ultimate target.
* For simplicity, these are all generically typed.
* @author jrose
*/
class FilterGeneric {
// type for the outgoing call (will be generic)
private final MethodType targetType;
// position of (first) argument to participate in filtering
private final short argumentPosition;
// number of arguments to participate in filtering
private final short argumentCount;
// how the result interacts with the filtered arguments: Prepend, Append, Replace, Discard
private final char replaceMode;
// prototype adapter (clone and customize for each new target & conversion!)
private final Adapter adapter;
// entry point for adapter (Adapter mh, a...) => ...
private final MethodHandle entryPoint;
// more of them (loosely cached)
private FilterGeneric variations;
/** Compute and cache information common to all unboxing adapters
* that can call out to targets of the erasure-family of the given erased type.
*/
// TO DO: Make this private.
FilterGeneric(MethodType targetType, short argumentPosition, short argumentCount, char replaceMode) {
if (argumentCount == 0) {
if (replaceMode == 'P' || replaceMode == 'A') replaceMode = 'R';
if (replaceMode == 'I') argumentPosition = 0;
}
this.targetType = targetType;
this.argumentPosition = argumentPosition;
this.argumentCount = argumentCount;
this.replaceMode = replaceMode;
validate(targetType, argumentPosition, argumentCount, replaceMode);
Adapter ad = findAdapter(targetType, argumentPosition, argumentCount, replaceMode, filterType());
if (ad == null)
ad = buildAdapterFromBytecodes(targetType, argumentPosition, argumentCount, replaceMode, filterType());
this.adapter = ad;
this.entryPoint = ad.prototypeEntryPoint();
}
Adapter makeInstance(MethodHandle filter, MethodHandle target) {
return adapter.makeInstance(entryPoint, filter, target);
}
/** Build an adapter of the given generic type, which invokes typedTarget
* on the incoming arguments, after unboxing as necessary.
* The return value is boxed if necessary.
* @param genericType the required type of the result
* @param typedTarget the target
* @return an adapter method handle
*/
public static MethodHandle make(MethodHandle target, int pos, MethodHandle filter) {
return FilterGeneric.of(target.type(), (short)pos, (short)1, 'R').makeInstance(filter, target);
}
/** Return the adapter information for this type's erasure. */
static FilterGeneric of(MethodType type, short ap, short ac, char mode) {
if (type.generic() != type)
throw new IllegalArgumentException("must be generic: "+type);
validate(type, ap, ac, mode);
MethodTypeImpl form = MethodTypeImpl.of(type);
FilterGeneric filterGen = form.filterGeneric;
if (filterGen == null)
form.filterGeneric = filterGen = new FilterGeneric(type, (short)0, (short)1, 'R');
return find(filterGen, ap, ac, mode);
}
static FilterGeneric find(FilterGeneric gen, short ap, short ac, char mode) {
for (;;) {
if (gen.argumentPosition == ap &&
gen.argumentCount == ac &&
gen.replaceMode == mode) {
return gen;
}
FilterGeneric gen2 = gen.variations;
if (gen2 == null) break;
gen = gen2;
}
FilterGeneric gen2 = new FilterGeneric(gen.targetType, ap, ac, mode);
gen.variations = gen2; // OK if this smashes another cached chain
return gen2;
}
private static void validate(MethodType type, short ap, short ac, char mode) {
int endpos = ap + ac;
switch (mode) {
case 'P': case 'A': case 'R': case 'D':
if (ap >= 0 && ac >= 0 &&
endpos >= 0 && endpos <= type.parameterCount())
return;
default:
throw new InternalError("configuration "+patternName(ap, ac, mode));
}
}
public String toString() {
return "FilterGeneric/"+patternName()+targetType;
}
String patternName() {
return patternName(argumentPosition, argumentCount, replaceMode);
}
static String patternName(short ap, short ac, char mode) {
return ""+mode+ap+(ac>1?"_"+ac:"");
}
Class<?> filterType() {
return Object.class; // result of filter operation; an uninteresting type
}
static MethodType targetType(MethodType entryType, short ap, short ac, char mode,
Class<?> arg) {
MethodType type = entryType;
int pos = ap;
switch (mode) {
case 'A':
pos += ac;
case 'P':
type = type.insertParameterType(pos, arg);
break;
case 'I':
for (int i = 1; i < ac; i++)
type = type.dropParameterType(pos);
assert(type.parameterType(pos) == arg);
break;
case 'D':
break;
}
return type;
}
static MethodType entryType(MethodType targetType, short ap, short ac, char mode,
Class<?> arg) {
MethodType type = targetType;
int pos = ap;
switch (mode) {
case 'A':
pos += ac;
case 'P':
type = type.dropParameterType(pos);
break;
case 'I':
for (int i = 1; i < ac; i++)
type = type.insertParameterType(pos, arg);
assert(type.parameterType(pos) == arg);
break;
case 'D':
break;
}
return type;
}
/* Create an adapter that handles spreading calls for the given type. */
static Adapter findAdapter(MethodType targetType, short ap, short ac, char mode, Class<?> arg) {
MethodType entryType = entryType(targetType, ap, ac, mode, arg);
int argc = targetType.parameterCount();
String pname = patternName(ap, ac, mode);
String cname0 = "F"+argc;
String cname1 = "F"+argc+mode;
String cname2 = "F"+argc+pname;
String[] cnames = { cname0, cname1, cname1+"X", cname2 };
String iname = "invoke_"+pname;
// e.g., F5R; invoke_R3
for (String cname : cnames) {
Class<? extends Adapter> acls = Adapter.findSubClass(cname);
if (acls == null) continue;
// see if it has the required invoke method
MethodHandle entryPoint = null;
try {
entryPoint = MethodHandleImpl.IMPL_LOOKUP.findSpecial(acls, iname, entryType, acls);
} catch (NoAccessException ex) {
}
if (entryPoint == null) continue;
Constructor<? extends Adapter> ctor = null;
try {
ctor = acls.getDeclaredConstructor(MethodHandle.class);
} catch (NoSuchMethodException ex) {
} catch (SecurityException ex) {
}
if (ctor == null) continue;
try {
// Produce an instance configured as a prototype.
return ctor.newInstance(entryPoint);
} catch (IllegalArgumentException ex) {
} catch (InvocationTargetException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
}
}
return null;
}
static Adapter buildAdapterFromBytecodes(MethodType targetType, short ap, short ac, char mode, Class<?> arg) {
throw new UnsupportedOperationException("NYI");
}
/**
* This adapter takes some untyped arguments, and returns an untyped result.
* Internally, it applies the invoker to the target, which causes the
* objects to be unboxed; the result is a raw type in L/I/J/F/D.
* This result is passed to convert, which is responsible for
* converting the raw result into a boxed object.
* The invoker is kept separate from the target because it can be
* generated once per type erasure family, and reused across adapters.
*/
static abstract class Adapter extends JavaMethodHandle {
protected final MethodHandle filter;
protected final MethodHandle target;
protected boolean isPrototype() { return target == null; }
protected Adapter(MethodHandle entryPoint) {
this(entryPoint, entryPoint, null);
assert(isPrototype());
}
protected MethodHandle prototypeEntryPoint() {
if (!isPrototype()) throw new InternalError();
return filter;
}
protected Adapter(MethodHandle entryPoint,
MethodHandle filter, MethodHandle target) {
super(entryPoint);
this.filter = filter;
this.target = target;
}
/** Make a copy of self, with new fields. */
protected abstract Adapter makeInstance(MethodHandle entryPoint,
MethodHandle filter, MethodHandle target);
// { return new ThisType(entryPoint, filter, target); }
static private final String CLASS_PREFIX; // "sun.dyn.FilterGeneric$"
static {
String aname = Adapter.class.getName();
String sname = Adapter.class.getSimpleName();
if (!aname.endsWith(sname)) throw new InternalError();
CLASS_PREFIX = aname.substring(0, aname.length() - sname.length());
}
/** Find a sibing class of Adapter. */
static Class<? extends Adapter> findSubClass(String name) {
String cname = Adapter.CLASS_PREFIX + name;
try {
return Class.forName(cname).asSubclass(Adapter.class);
} catch (ClassNotFoundException ex) {
return null;
} catch (ClassCastException ex) {
return null;
}
}
}
//* generated classes follow this pattern:
static class F1RX extends Adapter {
protected F1RX(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
protected F1RX(MethodHandle e, MethodHandle f, MethodHandle t)
{ super(e, f, t); }
protected F1RX makeInstance(MethodHandle e, MethodHandle f, MethodHandle t)
{ return new F1RX(e, f, t); }
protected Object filter(Object a0) { return filter.<Object>invoke(a0); }
protected Object target(Object a0) { return target.<Object>invoke(a0); }
protected Object invoke_R0(Object a0) { return target(filter(a0)); }
}
static class F2RX extends Adapter {
protected F2RX(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
protected F2RX(MethodHandle e, MethodHandle f, MethodHandle t)
{ super(e, f, t); }
protected F2RX makeInstance(MethodHandle e, MethodHandle f, MethodHandle t)
{ return new F2RX(e, f, t); }
protected Object filter(Object a0) { return filter.<Object>invoke(a0); }
protected Object target(Object a0, Object a1) { return target.<Object>invoke(a0, a1); }
protected Object invoke_R0(Object a0, Object a1) { return target(filter(a0), a1); }
protected Object invoke_R1(Object a0, Object a1) { return target(a0, filter(a1)); }
}
static class F3RX extends Adapter {
protected F3RX(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
protected F3RX(MethodHandle e, MethodHandle f, MethodHandle t)
{ super(e, f, t); }
protected F3RX makeInstance(MethodHandle e, MethodHandle f, MethodHandle t)
{ return new F3RX(e, f, t); }
protected Object filter(Object a0) { return filter.<Object>invoke(a0); }
protected Object target(Object a0, Object a1, Object a2) { return target.<Object>invoke(a0, a1, a2); }
protected Object invoke_R0(Object a0, Object a1, Object a2) { return target(filter(a0), a1, a2); }
protected Object invoke_R1(Object a0, Object a1, Object a2) { return target(a0, filter(a1), a2); }
protected Object invoke_R2(Object a0, Object a1, Object a2) { return target(a0, a1, filter(a2)); }
}
static class F4RX extends Adapter {
protected F4RX(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
protected F4RX(MethodHandle e, MethodHandle f, MethodHandle t)
{ super(e, f, t); }
protected F4RX makeInstance(MethodHandle e, MethodHandle f, MethodHandle t)
{ return new F4RX(e, f, t); }
protected Object filter(Object a0) { return filter.<Object>invoke(a0); }
protected Object target(Object a0, Object a1, Object a2, Object a3) { return target.<Object>invoke(a0, a1, a2, a3); }
protected Object invoke_R0(Object a0, Object a1, Object a2, Object a3) { return target(filter(a0), a1, a2, a3); }
protected Object invoke_R1(Object a0, Object a1, Object a2, Object a3) { return target(a0, filter(a1), a2, a3); }
protected Object invoke_R2(Object a0, Object a1, Object a2, Object a3) { return target(a0, a1, filter(a2), a3); }
protected Object invoke_R3(Object a0, Object a1, Object a2, Object a3) { return target(a0, a1, a2, filter(a3)); }
}
// */
}
/*
* Copyright 2008-2009 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package sun.dyn;
import java.dyn.JavaMethodHandle;
import java.dyn.MethodHandle;
import java.dyn.MethodHandles;
import java.dyn.MethodType;
/**
* Unary function composition, useful for many small plumbing jobs.
* The invoke method takes a single reference argument, and returns a reference
* Internally, it first calls the {@code filter} method on the argument,
* Making up the difference between the raw method type and the
* final method type is the responsibility of a JVM-level adapter.
* @author jrose
*/
public class FilterOneArgument extends JavaMethodHandle {
protected final MethodHandle filter; // Object -> Object
protected final MethodHandle target; // Object -> Object
protected Object entryPoint(Object argument) {
Object filteredArgument = filter.<Object>invoke(argument);
return target.<Object>invoke(filteredArgument);
}
private static final MethodHandle entryPoint =
MethodHandleImpl.IMPL_LOOKUP.findVirtual(FilterOneArgument.class, "entryPoint", MethodType.makeGeneric(1));
protected FilterOneArgument(MethodHandle filter, MethodHandle target) {
super(entryPoint);
this.filter = filter;
this.target = target;
}
public static MethodHandle make(MethodHandle filter, MethodHandle target) {
if (filter == null) return target;
if (target == null) return filter;
return new FilterOneArgument(filter, target);
}
public String toString() {
return filter + "|>" + target;
}
// MethodHandle make(MethodHandle filter1, MethodHandle filter2, MethodHandle target) {
// MethodHandle filter = make(filter1, filter2);
// return make(filter, target);
// }
}
此差异已折叠。
/*
* Copyright 2008-2009 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package sun.dyn;
import java.dyn.MethodHandle;
import java.dyn.MethodHandles;
import java.dyn.MethodType;
/**
* Construction and caching of often-used invokers.
* @author jrose
*/
public class Invokers {
// exact type (sans leading taget MH) for the outgoing call
private final MethodType targetType;
// exact invoker for the outgoing call
private /*lazy*/ MethodHandle exactInvoker;
// generic (untyped) invoker for the outgoing call
private /*lazy*/ MethodHandle genericInvoker;
/** Compute and cache information common to all collecting adapters
* that implement members of the erasure-family of the given erased type.
*/
public Invokers(Access token, MethodType targetType) {
Access.check(token);
this.targetType = targetType;
}
public static MethodType invokerType(MethodType targetType) {
return targetType.insertParameterType(0, MethodHandle.class);
}
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);
assert(invokerType(targetType) == invoker.type());
exactInvoker = invoker;
return invoker;
}
public MethodHandle genericInvoker() {
MethodHandle invoker1 = exactInvoker();
MethodHandle invoker = genericInvoker;
if (invoker != null) return invoker;
MethodType genericType = targetType.generic();
invoker = MethodHandles.convertArguments(invoker1, invokerType(genericType));
genericInvoker = invoker;
return invoker;
}
public MethodHandle varargsInvoker() {
throw new UnsupportedOperationException("NYI");
}
public String toString() {
return "Invokers"+targetType;
}
}
此差异已折叠。
/*
* Copyright 2008-2009 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package sun.dyn;
import java.dyn.MethodHandle;
import java.dyn.MethodHandles;
import java.dyn.MethodHandles.Lookup;
import java.dyn.MethodType;
import sun.dyn.util.VerifyType;
import java.dyn.NoAccessException;
import static sun.dyn.MemberName.newIllegalArgumentException;
import static sun.dyn.MemberName.newNoAccessException;
/**
* Base class for method handles, containing JVM-specific fields and logic.
* TO DO: It should not be a base class.
* @author jrose
*/
public abstract class MethodHandleImpl {
// Fields which really belong in MethodHandle:
private byte vmentry; // adapter stub or method entry point
//private int vmslots; // optionally, hoist type.form.vmslots
protected Object vmtarget; // VM-specific, class-specific target value
//MethodType type; // defined in MethodHandle
// TO DO: vmtarget should be invisible to Java, since the JVM puts internal
// managed pointers into it. Making it visible exposes it to debuggers,
// which can cause errors when they treat the pointer as an Object.
// These two dummy fields are present to force 'I' and 'J' signatures
// into this class's constant pool, so they can be transferred
// to vmentry when this class is loaded.
static final int INT_FIELD = 0;
static final long LONG_FIELD = 0;
// type is defined in java.dyn.MethodHandle, which is platform-independent
// vmentry (a void* field) is used *only* by by the JVM.
// The JVM adjusts its type to int or long depending on system wordsize.
// Since it is statically typed as neither int nor long, it is impossible
// to use this field from Java bytecode. (Please don't try to, either.)
// The vmentry is an assembly-language stub which is jumped to
// immediately after the method type is verified.
// For a direct MH, this stub loads the vmtarget's entry point
// and jumps to it.
/**
* VM-based method handles must have a security token.
* This security token can only be obtained by trusted code.
* Do not create method handles directly; use factory methods.
*/
public MethodHandleImpl(Access token) {
Access.check(token);
}
/** Initialize the method type form to participate in JVM calls.
* This is done once for each erased type.
*/
public static void init(Access token, MethodType self) {
Access.check(token);
if (MethodHandleNatives.JVM_SUPPORT)
MethodHandleNatives.init(self);
}
/// Factory methods to create method handles:
private static final MemberName.Factory LOOKUP = MemberName.Factory.INSTANCE;
static private Lookup IMPL_LOOKUP_INIT;
public static void initLookup(Access token, Lookup lookup) {
Access.check(token);
if (IMPL_LOOKUP_INIT != null || lookup.lookupClass() != Access.class)
throw new InternalError();
IMPL_LOOKUP_INIT = lookup;
}
public static Lookup getLookup(Access token) {
Access.check(token);
return IMPL_LOOKUP;
}
static {
// Force initialization:
Lookup.PUBLIC_LOOKUP.lookupClass();
if (IMPL_LOOKUP_INIT == null)
throw new InternalError();
}
public static void initStatics() {
// Trigger preceding sequence.
}
/** Shared secret with MethodHandles.Lookup, a copy of Lookup.IMPL_LOOKUP. */
static final Lookup IMPL_LOOKUP = IMPL_LOOKUP_INIT;
/** Look up a given method.
* Callable only from java.dyn and related packages.
* <p>
* The resulting method handle type will be of the given type,
* with a receiver type {@code rcvc} prepended if the member is not static.
* <p>
* Access checks are made as of the given lookup class.
* In particular, if the method is protected and {@code defc} is in a
* different package from the lookup class, then {@code rcvc} must be
* the lookup class or a subclass.
* @param token Proof that the lookup class has access to this package.
* @param member Resolved method or constructor to call.
* @param name Name of the desired method.
* @param rcvc Receiver type of desired non-static method (else null)
* @param doDispatch whether the method handle will test the receiver type
* @param lookupClass access-check relative to this class
* @return a direct handle to the matching method
* @throws NoAccessException if the given method cannot be accessed by the lookup class
*/
public static
MethodHandle findMethod(Access token, MemberName method,
boolean doDispatch, Class<?> lookupClass) {
Access.check(token); // only trusted calls
MethodType mtype = method.getMethodType();
if (method.isStatic()) {
doDispatch = false;
} else {
// adjust the advertised receiver type to be exactly the one requested
// (in the case of invokespecial, this will be the calling class)
mtype = mtype.insertParameterType(0, method.getDeclaringClass());
if (method.isConstructor())
doDispatch = true;
}
DirectMethodHandle mh = new DirectMethodHandle(mtype, method, doDispatch, lookupClass);
if (!mh.isValid())
throw newNoAccessException(method, lookupClass);
return mh;
}
public static
MethodHandle accessField(Access token,
MemberName member, boolean isSetter,
Class<?> lookupClass) {
Access.check(token);
// FIXME: Use sun.misc.Unsafe to dig up the dirt on the field.
throw new UnsupportedOperationException("Not yet implemented");
}
public static
MethodHandle accessArrayElement(Access token,
Class<?> arrayClass, boolean isSetter) {
Access.check(token);
if (!arrayClass.isArray())
throw newIllegalArgumentException("not an array: "+arrayClass);
// FIXME: Use sun.misc.Unsafe to dig up the dirt on the array.
throw new UnsupportedOperationException("Not yet implemented");
}
/** Bind a predetermined first argument to the given direct method handle.
* Callable only from MethodHandles.
* @param token Proof that the caller has access to this package.
* @param target Any direct method handle.
* @param receiver Receiver (or first static method argument) to pre-bind.
* @return a BoundMethodHandle for the given DirectMethodHandle, or null if it does not exist
*/
public static
MethodHandle bindReceiver(Access token,
MethodHandle target, Object receiver) {
Access.check(token);
if (target instanceof DirectMethodHandle)
return new BoundMethodHandle((DirectMethodHandle)target, receiver, 0);
return null; // let caller try something else
}
/** Bind a predetermined argument to the given arbitrary method handle.
* Callable only from MethodHandles.
* @param token Proof that the caller has access to this package.
* @param target Any method handle.
* @param receiver Argument (which can be a boxed primitive) to pre-bind.
* @return a suitable BoundMethodHandle
*/
public static
MethodHandle bindArgument(Access token,
MethodHandle target, int argnum, Object receiver) {
Access.check(token);
throw new UnsupportedOperationException("NYI");
}
public static MethodHandle convertArguments(Access token,
MethodHandle target,
MethodType newType,
MethodType oldType,
int[] permutationOrNull) {
Access.check(token);
MethodHandle res = AdapterMethodHandle.makePairwiseConvert(token, newType, target);
if (res != null)
return res;
int argc = oldType.parameterCount();
// The JVM can't do it directly, so fill in the gap with a Java adapter.
// TO DO: figure out what to put here from case-by-case experience
// Use a heavier method: Convert all the arguments to Object,
// then back to the desired types. We might have to use Java-based
// method handles to do this.
MethodType objType = MethodType.makeGeneric(argc);
MethodHandle objTarget = AdapterMethodHandle.makePairwiseConvert(token, objType, target);
if (objTarget == null)
objTarget = FromGeneric.make(target);
res = AdapterMethodHandle.makePairwiseConvert(token, newType, objTarget);
if (res != null)
return res;
return ToGeneric.make(newType, objTarget);
}
public static MethodHandle spreadArguments(Access token,
MethodHandle target,
MethodType newType,
int spreadArg) {
Access.check(token);
// TO DO: maybe allow the restarg to be Object and implicitly cast to Object[]
MethodType oldType = target.type();
// spread the last argument of newType to oldType
int spreadCount = oldType.parameterCount() - spreadArg;
Class<Object[]> spreadArgType = Object[].class;
MethodHandle res = AdapterMethodHandle.makeSpreadArguments(token, newType, target, spreadArgType, spreadArg, spreadCount);
if (res != null)
return res;
// try an intermediate adapter
Class<?> spreadType = null;
if (spreadArg < 0 || spreadArg >= newType.parameterCount()
|| !VerifyType.isSpreadArgType(spreadType = newType.parameterType(spreadArg)))
throw newIllegalArgumentException("no restarg in "+newType);
Class<?>[] ptypes = oldType.parameterArray();
for (int i = 0; i < spreadCount; i++)
ptypes[spreadArg + i] = VerifyType.spreadArgElementType(spreadType, i);
MethodType midType = MethodType.make(newType.returnType(), ptypes);
// after spreading, some arguments may need further conversion
target = convertArguments(token, target, midType, oldType, null);
if (target == null)
throw new UnsupportedOperationException("NYI: convert "+midType+" =calls=> "+oldType);
res = AdapterMethodHandle.makeSpreadArguments(token, newType, target, spreadArgType, spreadArg, spreadCount);
return res;
}
public static MethodHandle collectArguments(Access token,
MethodHandle target,
MethodType newType,
int collectArg) {
if (collectArg > 0)
throw new UnsupportedOperationException("NYI");
throw new UnsupportedOperationException("NYI");
}
public static
MethodHandle dropArguments(Access token, MethodHandle target,
MethodType newType, int argnum) {
Access.check(token);
throw new UnsupportedOperationException("NYI");
}
public static
MethodHandle makeGuardWithTest(Access token,
final MethodHandle test,
final MethodHandle target,
final MethodHandle fallback) {
Access.check(token);
// %%% This is just a sketch. It needs to be de-boxed.
// Adjust the handles to accept varargs lists.
MethodType type = target.type();
Class<?> rtype = type.returnType();
if (type.parameterCount() != 1 || type.parameterType(0).isPrimitive()) {
MethodType vatestType = MethodType.make(boolean.class, Object[].class);
MethodType vatargetType = MethodType.make(rtype, Object[].class);
MethodHandle vaguard = makeGuardWithTest(token,
MethodHandles.spreadArguments(test, vatestType),
MethodHandles.spreadArguments(target, vatargetType),
MethodHandles.spreadArguments(fallback, vatargetType));
return MethodHandles.collectArguments(vaguard, type);
}
if (rtype.isPrimitive()) {
MethodType boxtype = type.changeReturnType(Object.class);
MethodHandle boxguard = makeGuardWithTest(token,
test,
MethodHandles.convertArguments(target, boxtype),
MethodHandles.convertArguments(fallback, boxtype));
return MethodHandles.convertArguments(boxguard, type);
}
// Got here? Reduced calling sequence to Object(Object).
class Guarder {
Object invoke(Object x) {
// If javac supports MethodHandle.invoke directly:
//z = vatest.invoke<boolean>(arguments);
// If javac does not support direct MH.invoke calls:
boolean z = (Boolean) MethodHandles.invoke_1(test, x);
MethodHandle mh = (z ? target : fallback);
return MethodHandles.invoke_1(mh, x);
}
MethodHandle handle() {
MethodType invokeType = MethodType.makeGeneric(0, true);
MethodHandle vh = IMPL_LOOKUP.bind(this, "invoke", invokeType);
return MethodHandles.collectArguments(vh, target.type());
}
}
return new Guarder().handle();
}
public static
MethodHandle combineArguments(Access token, MethodHandle target, MethodHandle checker, int pos) {
Access.check(token);
throw new UnsupportedOperationException("Not yet implemented");
}
protected static String basicToString(MethodHandle target) {
MemberName name = null;
if (target != null)
name = MethodHandleNatives.getMethodName(target);
if (name == null)
return "<unknown>";
return name.getName();
}
protected static String addTypeString(MethodHandle target, String name) {
if (target == null) return name;
return name+target.type();
}
static RuntimeException newIllegalArgumentException(String string) {
return new IllegalArgumentException(string);
}
@Override
public String toString() {
MethodHandle self = (MethodHandle) this;
return addTypeString(self, basicToString(self));
}
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册