sun.reflect.Reflection.getCallerClass(int) is going to be removed... how to replace?
Hi all, The Oracle JDK internal method sun.reflect.Reflection. getCallerClass(int) is planned to be disabled in Oracle JDK 7u40. It is considered for removal in a later 7 update release. As you may be aware, the Oracle JDK internal sun.reflect.Reflection.getCallerClass(int) method has been removed from JDK 8. [1] The method is also planned [2] to be disabled in the 7u40 release. A call to the method would then trigger an UnsupportedOperationException. That means the method will be fully away for jdk8 and is going away in 7u40, but can still be enabled by a command line switch. There is a @CallSensitve annotation which allows calling Reflection.getCallerClass(). But this is causing some problems for us actually. Even if Reflection.getCallerClass() is ignoring all frames added by reflection (what about those added by invokedynamic/lambda?), it is not enough for us, since we will have also runtime generated classes appearing in there. A simple example is a Groovy program calling ResourceBundle#getBundle(String). While in non-indy mode the first access from that call site may be done by reflection and then work, subsequent calls would be done with runtime generated classes and then it can stop working very fast. Another one is Groovy grapes, which add libraries to the classpath at runtime, and it depends on being able to get the caller class loader for that. The usual depths here are 3-4, and that means 3-4 frames, that are not our callsite caching or indy, or reflection. With the runtime generated classes in the way I am not sure we can resolve the issue without really major changes, or we simply say that Groovy 2.x and earlier may not properly work on post jdk 7u40... unless you use indy, where I would still need confirmation there are no frames in the way from that then. I imagine other languages will have similar problems here and there... or not? bye Jochen -- Jochen blackdrag Theodorou - Groovy Project Tech Lead blog: http://blackdragsview.blogspot.com/ german groovy discussion newsgroup: de.comp.lang.misc For Groovy programming sources visit http://groovy-lang.org ___ mlvm-dev mailing list mlvm-dev@openjdk.java.net http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev
Re: sun.reflect.Reflection.getCallerClass(int) is going to be removed... how to replace?
FWIW, I'm currently working on Dynalink correctly supporting methods that are marked with @CallerSensitive; My tests from Nashorn show things work as expected, i.e. you can give some permissions to your script based on its URL in the security policy, and e.g. invoking AccessController.doPrivileged() through INVOKEDYNAMIC works as expected; it is actually a pretty big deal getting this to work right :-) (doPrivileged, of course, being @CallerSensitive). Attila. On Jul 2, 2013, at 2:56 PM, Jochen Theodorou blackd...@gmx.org wrote: Hi all, The Oracle JDK internal method sun.reflect.Reflection. getCallerClass(int) is planned to be disabled in Oracle JDK 7u40. It is considered for removal in a later 7 update release. As you may be aware, the Oracle JDK internal sun.reflect.Reflection.getCallerClass(int) method has been removed from JDK 8. [1] The method is also planned [2] to be disabled in the 7u40 release. A call to the method would then trigger an UnsupportedOperationException. That means the method will be fully away for jdk8 and is going away in 7u40, but can still be enabled by a command line switch. There is a @CallSensitve annotation which allows calling Reflection.getCallerClass(). But this is causing some problems for us actually. Even if Reflection.getCallerClass() is ignoring all frames added by reflection (what about those added by invokedynamic/lambda?), it is not enough for us, since we will have also runtime generated classes appearing in there. A simple example is a Groovy program calling ResourceBundle#getBundle(String). While in non-indy mode the first access from that call site may be done by reflection and then work, subsequent calls would be done with runtime generated classes and then it can stop working very fast. Another one is Groovy grapes, which add libraries to the classpath at runtime, and it depends on being able to get the caller class loader for that. The usual depths here are 3-4, and that means 3-4 frames, that are not our callsite caching or indy, or reflection. With the runtime generated classes in the way I am not sure we can resolve the issue without really major changes, or we simply say that Groovy 2.x and earlier may not properly work on post jdk 7u40... unless you use indy, where I would still need confirmation there are no frames in the way from that then. I imagine other languages will have similar problems here and there... or not? bye Jochen -- Jochen blackdrag Theodorou - Groovy Project Tech Lead blog: http://blackdragsview.blogspot.com/ german groovy discussion newsgroup: de.comp.lang.misc For Groovy programming sources visit http://groovy-lang.org ___ mlvm-dev mailing list mlvm-dev@openjdk.java.net http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev ___ mlvm-dev mailing list mlvm-dev@openjdk.java.net http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev
Re: sun.reflect.Reflection.getCallerClass(int) is going to be removed... how to replace?
On Tue, Jul 2, 2013 at 2:56 PM, Jochen Theodorou blackd...@gmx.org wrote: I imagine other languages will have similar problems here and there... or not? Hmm... what are you using that method for? I'm not aware of uses of it in ABCL, but that may be because we aren't smart enough... ;) ___ mlvm-dev mailing list mlvm-dev@openjdk.java.net http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev
Re: sun.reflect.Reflection.getCallerClass(int) is going to be removed... how to replace?
Am 02.07.2013 15:10, schrieb Attila Szegedi: FWIW, I'm currently working on Dynalink correctly supporting methods that are marked with @CallerSensitive; My tests from Nashorn show things work as expected, i.e. you can give some permissions to your script based on its URL in the security policy, and e.g. invoking AccessController.doPrivileged() through INVOKEDYNAMIC works as expected; it is actually a pretty big deal getting this to work right :-) (doPrivileged, of course, being @CallerSensitive). I imagine INVOKEDYNAMIC may not have a problem here, if additional frames added by it are taken into account as well. But in Groovy we have not only invokedynamic and reflection. bye Jochen -- Jochen blackdrag Theodorou - Groovy Project Tech Lead blog: http://blackdragsview.blogspot.com/ german groovy discussion newsgroup: de.comp.lang.misc For Groovy programming sources visit http://groovy-lang.org ___ mlvm-dev mailing list mlvm-dev@openjdk.java.net http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev
Re: sun.reflect.Reflection.getCallerClass(int) is going to be removed... how to replace?
Am 02.07.2013 15:10, schrieb Alessio Stalla: On Tue, Jul 2, 2013 at 2:56 PM, Jochen Theodorou blackd...@gmx.org wrote: I imagine other languages will have similar problems here and there... or not? Hmm... what are you using that method for? I'm not aware of uses of it in ABCL, but that may be because we aren't smart enough... ;) for example... Class.forName(String). Not that I advice people using this at any time, but this class gets the caller class, to use its class loader, to load a class by name. If your language does not generate a direct method call, then the code in forName assumes, that additional frame by you is the caller and uses its classloader instead the real one. There are many such things, but I don't know if they are relevant for ABCL. bye Jochen -- Jochen blackdrag Theodorou - Groovy Project Tech Lead blog: http://blackdragsview.blogspot.com/ german groovy discussion newsgroup: de.comp.lang.misc For Groovy programming sources visit http://groovy-lang.org ___ mlvm-dev mailing list mlvm-dev@openjdk.java.net http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev
Re: sun.reflect.Reflection.getCallerClass(int) is going to be removed... how to replace?
On Jul 2, 2013, at 7:00 AM, Jochen Theodorou blackd...@gmx.org wrote: for example... Class.forName(String) That's a good example. If you call Class.forName via reflection, it will sense its immediate caller, which (depending on your system) might be a random frame in your language runtime. This approach gets wrong answers by accident, which sometimes causes subtle problems. When your language runtime has a different privilege level than the script, you can get confusion about which privilege level is supposed to apply to the requested class name resolution. This could lead to untimely surprises. If you call Class.forName via a method handle in early versions of JDK 7, similar things can happen. In more recent versions of JSR 292, when you look up a method handle that is known to be caller-sensitive, the call to Lookup.findStatic (for example) returns a caller-bound version of the method handle, which is permanently bound to the lookup class of the lookup object you used to find the method handle. Then, regardless of where that MH gets installed or used (in some random MH graph, or directly in an invokedynamic) the caller sensitive aspect is always the same. (Fine print: This behavior is a corollary of the originally specified nature of MHs in terms of their bytecode behavior, since the bytecode behavior of a CS method includes the class holding the bytecodes performing the invoke. Note that this does not work for publicLookup, since that guy doesn't possess a knowable containing class for his bytecode behaviors.) The upshot of all this is that if you encapsulate your CS method calls in method handles obtained from a BSM or MethodHandles.lookup, your code won't be sensitive to the dynamic context of those calls. On Jul 2, 2013, at 5:56 AM, Jochen Theodorou blackd...@gmx.org wrote: A simple example is a Groovy program calling ResourceBundle#getBundle(String) The same considerations apply to resource bundles also. Basically, if you use Method.invoke on a caller sensitive method, it may sense a random caller. Use method handles for these cases, if possible. — John___ mlvm-dev mailing list mlvm-dev@openjdk.java.net http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev
hg: mlvm/mlvm/jdk: meth-info-8008688.patch: fix regression on BigArityTest
Changeset: a49289c99587 Author:jrose Date: 2013-07-02 17:15 -0700 URL: http://hg.openjdk.java.net/mlvm/mlvm/jdk/rev/a49289c99587 meth-info-8008688.patch: fix regression on BigArityTest ! meth-info-8008688.patch ___ mlvm-dev mailing list mlvm-dev@openjdk.java.net http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev
hg: mlvm/mlvm/jdk: meth-info-8008688.patch: incorporate review comments
Changeset: 5e0f932f8ef0 Author:jrose Date: 2013-07-02 18:23 -0700 URL: http://hg.openjdk.java.net/mlvm/mlvm/jdk/rev/5e0f932f8ef0 meth-info-8008688.patch: incorporate review comments ! meth-info-8008688.patch ___ mlvm-dev mailing list mlvm-dev@openjdk.java.net http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev
Re: RFR(L): 8008688: Make MethodHandleInfo public
Couldn't find any obvious problems. Looks good. -- Chris On Jul 2, 2013, at 6:26 PM, John Rose john.r.r...@oracle.com wrote: Thanks for the helpful review, Vladimir. I have incorporated all your comments and updated the webrev here: http://cr.openjdk.java.net/~jrose/8008688/webrev.05 Detailed replies follow. On Jul 1, 2013, at 3:36 PM, Vladimir Ivanov vladimir.x.iva...@oracle.com wrote: John, I have some minor suggestions about code style and code readability. Otherwise, the change looks good! src/share/classes/java/lang/invoke/MemberName.java: public MemberName(Method m, boolean wantSpecial) { ... MethodHandleNatives.init(this, m); +if (clazz == null) { // MHN.init failed +if (m.getDeclaringClass() == MethodHandle.class +isMethodHandleInvokeName(m.getName())) { Please, add a comment with a short description why a custom init procedure for MH.invoke* cases is needed. Done: // The JVM did not reify this signature-polymorphic instance. // Need a special case here. // See comments on MethodHandleNatives.linkMethod. And I added several paragraphs in the javadoc for linkMethod. They cover non-reification, linker methods, appendixes, synthetic, varargs, and more. +/** Create a name for a signature-polymorphic invoker. */ +static MemberName makeMethodHandleInvoke(String name, MethodType type) { +return makeMethodHandleInvoke(name, type, MH_INVOKE_MODS | SYNTHETIC); Please, add a comment why SYNTHETIC flag is necessary. /** * Create a name for a signature-polymorphic invoker. * This is a placeholder for a signature-polymorphic instance * (of MH.invokeExact, etc.) that the JVM does not reify. * See comments on {@link MethodHandleNatives#linkMethod}. */ src/share/classes/java/lang/invoke/MethodHandleInfo.java: src/share/classes/java/lang/invoke/MethodHandles.java: +import java.security.*; This import isn't used. Fixed. src/share/classes/java/lang/invoke/MethodHandles.java: +public MethodHandleInfo revealDirect(MethodHandle target) { ... +byte refKind = member.getReferenceKind(); ... +// Check SM permissions and member access before cracking. +try { +//@@checkSecurityManager(defc, member, lookupClass()); +checkSecurityManager(defc, member); +checkAccess(member.getReferenceKind(), defc, member); +} catch (IllegalAccessException ex) { +throw new IllegalArgumentException(ex); +} You prepare a separate refKind for MethodHandleInfo, but perform security checks against original member.getReferenceKind(). Is it intentional? No, it's bug. Thanks for catching that. src/share/classes/java/lang/invoke/InfoFromMemberName.java: 81 public T extends Member T reflectAs(ClassT expected, Lookup lookup) { 82 if (member.isMethodHandleInvoke() !member.isVarargs()) { 83 // this member is an instance of a signature-polymorphic method, which cannot be reflected 84 throw new IllegalArgumentException(cannot reflect signature polymorphic method); Please, add a comment why (!member.isVarargs()) check is necessary. // This member is an instance of a signature-polymorphic method, which cannot be reflected // A method handle invoker can come in either of two forms: // A generic placeholder (present in the source code, and varargs) // and a signature-polymorphic instance (synthetic and not varargs). // For more information see comments on {@link MethodHandleNatives#linkMethod}. src/share/classes/java/lang/invoke/InfoFromMemberName.java: 127 private void checkAccess(Member mem, Lookup lookup) throws IllegalAccessException { 128 byte refKind = (byte) getReferenceKind(); 129 if (mem instanceof Method) { 130 boolean wantSpecial = (refKind == REF_invokeSpecial); 131 lookup.checkAccess(refKind, getDeclaringClass(), new MemberName((Method) mem, wantSpecial)); 132 } else if (mem instanceof Constructor) { 133 lookup.checkAccess(refKind, getDeclaringClass(), new MemberName((Constructor) mem)); 134 } else if (mem instanceof Field) { 135 boolean isSetter = (refKind == REF_putField || refKind == REF_putStatic); 136 lookup.checkAccess(refKind, getDeclaringClass(), new MemberName((Field) mem, isSetter)); 137 } 138 } Can you introduce a factory method to convert a Member instance into MemberName and call lookup.checkAccess(refKind, getDeclaringClass(), covertToMemberName(mem)) instead? It'll considerably simplify the code and make the intention clearer. Good idea. Done. — John Best regards, Vladimir Ivanov On 6/27/13