< prev index next >

src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java

Print this page
rev 59151 : imported patch viewAs


  34 import sun.invoke.util.Wrapper;
  35 
  36 import java.lang.ref.WeakReference;
  37 import java.util.Arrays;
  38 import java.util.Objects;
  39 
  40 import static java.lang.invoke.LambdaForm.*;
  41 import static java.lang.invoke.LambdaForm.Kind.*;
  42 import static java.lang.invoke.MethodHandleNatives.Constants.*;
  43 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
  44 import static java.lang.invoke.MethodHandleStatics.newInternalError;
  45 import static java.lang.invoke.MethodTypeForm.*;
  46 
  47 /**
  48  * The flavor of method handle which implements a constant reference
  49  * to a class member.
  50  * @author jrose
  51  */
  52 class DirectMethodHandle extends MethodHandle {
  53     final MemberName member;

  54 
  55     // Constructors and factory methods in this class *must* be package scoped or private.
  56     private DirectMethodHandle(MethodType mtype, LambdaForm form, MemberName member) {
  57         super(mtype, form);
  58         if (!member.isResolved())  throw new InternalError();
  59 
  60         if (member.getDeclaringClass().isInterface() &&
  61             member.getReferenceKind() == REF_invokeInterface &&
  62             member.isMethod() && !member.isAbstract()) {
  63             // Check for corner case: invokeinterface of Object method
  64             MemberName m = new MemberName(Object.class, member.getName(), member.getMethodType(), member.getReferenceKind());
  65             m = MemberName.getFactory().resolveOrNull(m.getReferenceKind(), m, null);
  66             if (m != null && m.isPublic()) {
  67                 assert(member.getReferenceKind() == m.getReferenceKind());  // else this.form is wrong
  68                 member = m;
  69             }
  70         }
  71 
  72         this.member = member;

  73     }
  74 
  75     // Factory methods:
  76     static DirectMethodHandle make(byte refKind, Class<?> refc, MemberName member, Class<?> callerClass) {
  77         MethodType mtype = member.getMethodOrFieldType();
  78         if (!member.isStatic()) {
  79             if (!member.getDeclaringClass().isAssignableFrom(refc) || member.isConstructor())
  80                 throw new InternalError(member.toString());
  81             mtype = mtype.insertParameterTypes(0, refc);
  82         }
  83         if (!member.isField()) {
  84             // refKind reflects the original type of lookup via findSpecial or
  85             // findVirtual etc.
  86             switch (refKind) {
  87                 case REF_invokeSpecial: {
  88                     member = member.asSpecial();
  89                     // if caller is an interface we need to adapt to get the
  90                     // receiver check inserted
  91                     if (callerClass == null) {
  92                         throw new InternalError("callerClass must not be null for REF_invokeSpecial");
  93                     }
  94                     LambdaForm lform = preparedLambdaForm(member, callerClass.isInterface());
  95                     return new Special(mtype, lform, member, callerClass);
  96                 }
  97                 case REF_invokeInterface: {
  98                     // for interfaces we always need the receiver typecheck,
  99                     // so we always pass 'true' to ensure we adapt if needed
 100                     // to include the REF_invokeSpecial case
 101                     LambdaForm lform = preparedLambdaForm(member, true);
 102                     return new Interface(mtype, lform, member, refc);
 103                 }
 104                 default: {
 105                     LambdaForm lform = preparedLambdaForm(member);
 106                     return new DirectMethodHandle(mtype, lform, member);
 107                 }
 108             }
 109         } else {
 110             LambdaForm lform = preparedFieldLambdaForm(member);
 111             if (member.isStatic()) {
 112                 long offset = MethodHandleNatives.staticFieldOffset(member);
 113                 Object base = MethodHandleNatives.staticFieldBase(member);
 114                 return new StaticAccessor(mtype, lform, member, base, offset);
 115             } else {
 116                 long offset = MethodHandleNatives.objectFieldOffset(member);
 117                 assert(offset == (int)offset);
 118                 return new Accessor(mtype, lform, member, (int)offset);
 119             }
 120         }
 121     }
 122     static DirectMethodHandle make(Class<?> refc, MemberName member) {
 123         byte refKind = member.getReferenceKind();
 124         if (refKind == REF_invokeSpecial)
 125             refKind =  REF_invokeVirtual;
 126         return make(refKind, refc, member, null /* no callerClass context */);
 127     }
 128     static DirectMethodHandle make(MemberName member) {
 129         if (member.isConstructor())
 130             return makeAllocator(member);
 131         return make(member.getDeclaringClass(), member);
 132     }
 133     private static DirectMethodHandle makeAllocator(MemberName ctor) {
 134         assert(ctor.isConstructor() && ctor.getName().equals("<init>"));
 135         Class<?> instanceClass = ctor.getDeclaringClass();
 136         ctor = ctor.asConstructor();
 137         assert(ctor.isConstructor() && ctor.getReferenceKind() == REF_newInvokeSpecial) : ctor;
 138         MethodType mtype = ctor.getMethodType().changeReturnType(instanceClass);
 139         LambdaForm lform = preparedLambdaForm(ctor);
 140         MemberName init = ctor.asSpecial();
 141         assert(init.getMethodType().returnType() == void.class);
 142         return new Constructor(mtype, lform, ctor, init, instanceClass);
 143     }
 144 
 145     @Override
 146     BoundMethodHandle rebind() {
 147         return BoundMethodHandle.makeReinvoker(this);
 148     }
 149 
 150     @Override
 151     MethodHandle copyWith(MethodType mt, LambdaForm lf) {
 152         assert(this.getClass() == DirectMethodHandle.class);  // must override in subclasses
 153         return new DirectMethodHandle(mt, lf, member);















 154     }
 155 

 156     @Override
 157     String internalProperties() {
 158         return "\n& DMH.MN="+internalMemberName();
 159     }
 160 
 161     //// Implementation methods.
 162     @Override
 163     @ForceInline
 164     MemberName internalMemberName() {
 165         return member;
 166     }
 167 
 168     private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
 169 
 170     /**
 171      * Create a LF which can invoke the given method.
 172      * Cache and share this structure among all methods with
 173      * the same basicType and refKind.
 174      */
 175     private static LambdaForm preparedLambdaForm(MemberName m, boolean adaptToSpecialIfc) {


 389                 // Yes, we are running it; keep the barrier for now.
 390                 return false;
 391         } else {
 392             // We are in a random thread.  Block.
 393             UNSAFE.ensureClassInitialized(defc);
 394         }
 395         assert(!UNSAFE.shouldBeInitialized(defc));
 396         // put it into the final state
 397         EnsureInitialized.INSTANCE.remove(defc);
 398         return true;
 399     }
 400 
 401     /*non-public*/
 402     static void ensureInitialized(Object mh) {
 403         ((DirectMethodHandle)mh).ensureInitialized();
 404     }
 405 
 406     /** This subclass represents invokespecial instructions. */
 407     static class Special extends DirectMethodHandle {
 408         private final Class<?> caller;
 409         private Special(MethodType mtype, LambdaForm form, MemberName member, Class<?> caller) {
 410             super(mtype, form, member);
 411             this.caller = caller;
 412         }
 413         @Override
 414         boolean isInvokeSpecial() {
 415             return true;
 416         }
 417         @Override
 418         MethodHandle copyWith(MethodType mt, LambdaForm lf) {
 419             return new Special(mt, lf, member, caller);





 420         }
 421         Object checkReceiver(Object recv) {
 422             if (!caller.isInstance(recv)) {
 423                 String msg = String.format("Receiver class %s is not a subclass of caller class %s",
 424                                            recv.getClass().getName(), caller.getName());
 425                 throw new IncompatibleClassChangeError(msg);
 426             }
 427             return recv;
 428         }
 429     }
 430 
 431     /** This subclass represents invokeinterface instructions. */
 432     static class Interface extends DirectMethodHandle {
 433         private final Class<?> refc;
 434         private Interface(MethodType mtype, LambdaForm form, MemberName member, Class<?> refc) {
 435             super(mtype, form, member);
 436             assert refc.isInterface() : refc;
 437             this.refc = refc;
 438         }
 439         @Override
 440         MethodHandle copyWith(MethodType mt, LambdaForm lf) {
 441             return new Interface(mt, lf, member, refc);





 442         }
 443         @Override
 444         Object checkReceiver(Object recv) {
 445             if (!refc.isInstance(recv)) {
 446                 String msg = String.format("Receiver class %s does not implement the requested interface %s",
 447                                            recv.getClass().getName(), refc.getName());
 448                 throw new IncompatibleClassChangeError(msg);
 449             }
 450             return recv;
 451         }
 452     }
 453 
 454     /** Used for interface receiver type checks, by Interface and Special modes. */
 455     Object checkReceiver(Object recv) {
 456         throw new InternalError("Should only be invoked on a subclass");
 457     }
 458 
 459 
 460     /** This subclass handles constructor references. */
 461     static class Constructor extends DirectMethodHandle {
 462         final MemberName initMethod;
 463         final Class<?>   instanceClass;
 464 
 465         private Constructor(MethodType mtype, LambdaForm form, MemberName constructor,
 466                             MemberName initMethod, Class<?> instanceClass) {
 467             super(mtype, form, constructor);
 468             this.initMethod = initMethod;
 469             this.instanceClass = instanceClass;
 470             assert(initMethod.isResolved());
 471         }
 472         @Override
 473         MethodHandle copyWith(MethodType mt, LambdaForm lf) {
 474             return new Constructor(mt, lf, member, initMethod, instanceClass);





 475         }
 476     }
 477 
 478     /*non-public*/
 479     static Object constructorMethod(Object mh) {
 480         Constructor dmh = (Constructor)mh;
 481         return dmh.initMethod;
 482     }
 483 
 484     /*non-public*/
 485     static Object allocateInstance(Object mh) throws InstantiationException {
 486         Constructor dmh = (Constructor)mh;
 487         return UNSAFE.allocateInstance(dmh.instanceClass);
 488     }
 489 
 490     /** This subclass handles non-static field references. */
 491     static class Accessor extends DirectMethodHandle {
 492         final Class<?> fieldType;
 493         final int      fieldOffset;
 494         private Accessor(MethodType mtype, LambdaForm form, MemberName member,
 495                          int fieldOffset) {
 496             super(mtype, form, member);
 497             this.fieldType   = member.getFieldType();
 498             this.fieldOffset = fieldOffset;
 499         }
 500 
 501         @Override Object checkCast(Object obj) {
 502             return fieldType.cast(obj);
 503         }
 504         @Override
 505         MethodHandle copyWith(MethodType mt, LambdaForm lf) {
 506             return new Accessor(mt, lf, member, fieldOffset);





 507         }
 508     }
 509 
 510     @ForceInline
 511     /*non-public*/
 512     static long fieldOffset(Object accessorObj) {
 513         // Note: We return a long because that is what Unsafe.getObject likes.
 514         // We store a plain int because it is more compact.
 515         return ((Accessor)accessorObj).fieldOffset;
 516     }
 517 
 518     @ForceInline
 519     /*non-public*/
 520     static Object checkBase(Object obj) {
 521         // Note that the object's class has already been verified,
 522         // since the parameter type of the Accessor method handle
 523         // is either member.getDeclaringClass or a subclass.
 524         // This was verified in DirectMethodHandle.make.
 525         // Therefore, the only remaining check is for null.
 526         // Since this check is *not* guaranteed by Unsafe.getInt
 527         // and its siblings, we need to make an explicit one here.
 528         return Objects.requireNonNull(obj);
 529     }
 530 
 531     /** This subclass handles static field references. */
 532     static class StaticAccessor extends DirectMethodHandle {
 533         private final Class<?> fieldType;
 534         private final Object   staticBase;
 535         private final long     staticOffset;
 536 
 537         private StaticAccessor(MethodType mtype, LambdaForm form, MemberName member,
 538                                Object staticBase, long staticOffset) {
 539             super(mtype, form, member);
 540             this.fieldType    = member.getFieldType();
 541             this.staticBase   = staticBase;
 542             this.staticOffset = staticOffset;
 543         }
 544 
 545         @Override Object checkCast(Object obj) {
 546             return fieldType.cast(obj);
 547         }
 548         @Override
 549         MethodHandle copyWith(MethodType mt, LambdaForm lf) {
 550             return new StaticAccessor(mt, lf, member, staticBase, staticOffset);





 551         }
 552     }
 553 
 554     @ForceInline
 555     /*non-public*/
 556     static Object nullCheck(Object obj) {
 557         return Objects.requireNonNull(obj);
 558     }
 559 
 560     @ForceInline
 561     /*non-public*/
 562     static Object staticBase(Object accessorObj) {
 563         return ((StaticAccessor)accessorObj).staticBase;
 564     }
 565 
 566     @ForceInline
 567     /*non-public*/
 568     static long staticOffset(Object accessorObj) {
 569         return ((StaticAccessor)accessorObj).staticOffset;
 570     }




  34 import sun.invoke.util.Wrapper;
  35 
  36 import java.lang.ref.WeakReference;
  37 import java.util.Arrays;
  38 import java.util.Objects;
  39 
  40 import static java.lang.invoke.LambdaForm.*;
  41 import static java.lang.invoke.LambdaForm.Kind.*;
  42 import static java.lang.invoke.MethodHandleNatives.Constants.*;
  43 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
  44 import static java.lang.invoke.MethodHandleStatics.newInternalError;
  45 import static java.lang.invoke.MethodTypeForm.*;
  46 
  47 /**
  48  * The flavor of method handle which implements a constant reference
  49  * to a class member.
  50  * @author jrose
  51  */
  52 class DirectMethodHandle extends MethodHandle {
  53     final MemberName member;
  54     final boolean crackable;
  55 
  56     // Constructors and factory methods in this class *must* be package scoped or private.
  57     private DirectMethodHandle(MethodType mtype, LambdaForm form, MemberName member, boolean crackable) {
  58         super(mtype, form);
  59         if (!member.isResolved())  throw new InternalError();
  60 
  61         if (member.getDeclaringClass().isInterface() &&
  62             member.getReferenceKind() == REF_invokeInterface &&
  63             member.isMethod() && !member.isAbstract()) {
  64             // Check for corner case: invokeinterface of Object method
  65             MemberName m = new MemberName(Object.class, member.getName(), member.getMethodType(), member.getReferenceKind());
  66             m = MemberName.getFactory().resolveOrNull(m.getReferenceKind(), m, null);
  67             if (m != null && m.isPublic()) {
  68                 assert(member.getReferenceKind() == m.getReferenceKind());  // else this.form is wrong
  69                 member = m;
  70             }
  71         }
  72 
  73         this.member = member;
  74         this.crackable = crackable;
  75     }
  76 
  77     // Factory methods:
  78     static DirectMethodHandle make(byte refKind, Class<?> refc, MemberName member, Class<?> callerClass) {
  79         MethodType mtype = member.getMethodOrFieldType();
  80         if (!member.isStatic()) {
  81             if (!member.getDeclaringClass().isAssignableFrom(refc) || member.isConstructor())
  82                 throw new InternalError(member.toString());
  83             mtype = mtype.insertParameterTypes(0, refc);
  84         }
  85         if (!member.isField()) {
  86             // refKind reflects the original type of lookup via findSpecial or
  87             // findVirtual etc.
  88             switch (refKind) {
  89                 case REF_invokeSpecial: {
  90                     member = member.asSpecial();
  91                     // if caller is an interface we need to adapt to get the
  92                     // receiver check inserted
  93                     if (callerClass == null) {
  94                         throw new InternalError("callerClass must not be null for REF_invokeSpecial");
  95                     }
  96                     LambdaForm lform = preparedLambdaForm(member, callerClass.isInterface());
  97                     return new Special(mtype, lform, member, true, callerClass);
  98                 }
  99                 case REF_invokeInterface: {
 100                     // for interfaces we always need the receiver typecheck,
 101                     // so we always pass 'true' to ensure we adapt if needed
 102                     // to include the REF_invokeSpecial case
 103                     LambdaForm lform = preparedLambdaForm(member, true);
 104                     return new Interface(mtype, lform, member, true, refc);
 105                 }
 106                 default: {
 107                     LambdaForm lform = preparedLambdaForm(member);
 108                     return new DirectMethodHandle(mtype, lform, member, true);
 109                 }
 110             }
 111         } else {
 112             LambdaForm lform = preparedFieldLambdaForm(member);
 113             if (member.isStatic()) {
 114                 long offset = MethodHandleNatives.staticFieldOffset(member);
 115                 Object base = MethodHandleNatives.staticFieldBase(member);
 116                 return new StaticAccessor(mtype, lform, member, true, base, offset);
 117             } else {
 118                 long offset = MethodHandleNatives.objectFieldOffset(member);
 119                 assert(offset == (int)offset);
 120                 return new Accessor(mtype, lform, member, true, (int)offset);
 121             }
 122         }
 123     }
 124     static DirectMethodHandle make(Class<?> refc, MemberName member) {
 125         byte refKind = member.getReferenceKind();
 126         if (refKind == REF_invokeSpecial)
 127             refKind =  REF_invokeVirtual;
 128         return make(refKind, refc, member, null /* no callerClass context */);
 129     }
 130     static DirectMethodHandle make(MemberName member) {
 131         if (member.isConstructor())
 132             return makeAllocator(member);
 133         return make(member.getDeclaringClass(), member);
 134     }
 135     private static DirectMethodHandle makeAllocator(MemberName ctor) {
 136         assert(ctor.isConstructor() && ctor.getName().equals("<init>"));
 137         Class<?> instanceClass = ctor.getDeclaringClass();
 138         ctor = ctor.asConstructor();
 139         assert(ctor.isConstructor() && ctor.getReferenceKind() == REF_newInvokeSpecial) : ctor;
 140         MethodType mtype = ctor.getMethodType().changeReturnType(instanceClass);
 141         LambdaForm lform = preparedLambdaForm(ctor);
 142         MemberName init = ctor.asSpecial();
 143         assert(init.getMethodType().returnType() == void.class);
 144         return new Constructor(mtype, lform, ctor, true, init, instanceClass);
 145     }
 146 
 147     @Override
 148     BoundMethodHandle rebind() {
 149         return BoundMethodHandle.makeReinvoker(this);
 150     }
 151 
 152     @Override
 153     MethodHandle copyWith(MethodType mt, LambdaForm lf) {
 154         assert(this.getClass() == DirectMethodHandle.class);  // must override in subclasses
 155         return new DirectMethodHandle(mt, lf, member, crackable);
 156     }
 157     /*non-public*/
 158     @Override
 159     MethodHandle viewAsType(MethodType newType, boolean strict) {
 160         // No actual conversions, just a new view of the same method.
 161         // However, we must not expose a DMH that is crackable into a
 162         // MethodHandleInfo, so we return a cloned, uncrackable DMH
 163         assert viewAsTypeChecks(newType, strict);
 164         assert(this.getClass() == DirectMethodHandle.class);  // must override in subclasses
 165         return new DirectMethodHandle(newType, form, member, false);
 166     }
 167     /*non-public*/
 168     @Override
 169     boolean isCrackable() {
 170         return crackable;
 171     }
 172 
 173 
 174     @Override
 175     String internalProperties() {
 176         return "\n& DMH.MN="+internalMemberName();
 177     }
 178 
 179     //// Implementation methods.
 180     @Override
 181     @ForceInline
 182     MemberName internalMemberName() {
 183         return member;
 184     }
 185 
 186     private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
 187 
 188     /**
 189      * Create a LF which can invoke the given method.
 190      * Cache and share this structure among all methods with
 191      * the same basicType and refKind.
 192      */
 193     private static LambdaForm preparedLambdaForm(MemberName m, boolean adaptToSpecialIfc) {


 407                 // Yes, we are running it; keep the barrier for now.
 408                 return false;
 409         } else {
 410             // We are in a random thread.  Block.
 411             UNSAFE.ensureClassInitialized(defc);
 412         }
 413         assert(!UNSAFE.shouldBeInitialized(defc));
 414         // put it into the final state
 415         EnsureInitialized.INSTANCE.remove(defc);
 416         return true;
 417     }
 418 
 419     /*non-public*/
 420     static void ensureInitialized(Object mh) {
 421         ((DirectMethodHandle)mh).ensureInitialized();
 422     }
 423 
 424     /** This subclass represents invokespecial instructions. */
 425     static class Special extends DirectMethodHandle {
 426         private final Class<?> caller;
 427         private Special(MethodType mtype, LambdaForm form, MemberName member, boolean crackable, Class<?> caller) {
 428             super(mtype, form, member, crackable);
 429             this.caller = caller;
 430         }
 431         @Override
 432         boolean isInvokeSpecial() {
 433             return true;
 434         }
 435         @Override
 436         MethodHandle copyWith(MethodType mt, LambdaForm lf) {
 437             return new Special(mt, lf, member, crackable, caller);
 438         }
 439         @Override
 440         MethodHandle viewAsType(MethodType newType, boolean strict) {
 441             assert viewAsTypeChecks(newType, strict);
 442             return new Special(newType, form, member, false, caller);
 443         }
 444         Object checkReceiver(Object recv) {
 445             if (!caller.isInstance(recv)) {
 446                 String msg = String.format("Receiver class %s is not a subclass of caller class %s",
 447                                            recv.getClass().getName(), caller.getName());
 448                 throw new IncompatibleClassChangeError(msg);
 449             }
 450             return recv;
 451         }
 452     }
 453 
 454     /** This subclass represents invokeinterface instructions. */
 455     static class Interface extends DirectMethodHandle {
 456         private final Class<?> refc;
 457         private Interface(MethodType mtype, LambdaForm form, MemberName member, boolean crackable, Class<?> refc) {
 458             super(mtype, form, member, crackable);
 459             assert refc.isInterface() : refc;
 460             this.refc = refc;
 461         }
 462         @Override
 463         MethodHandle copyWith(MethodType mt, LambdaForm lf) {
 464             return new Interface(mt, lf, member, crackable, refc);
 465         }
 466         @Override
 467         MethodHandle viewAsType(MethodType newType, boolean strict) {
 468             assert viewAsTypeChecks(newType, strict);
 469             return new Interface(newType, form, member, false, refc);
 470         }
 471         @Override
 472         Object checkReceiver(Object recv) {
 473             if (!refc.isInstance(recv)) {
 474                 String msg = String.format("Receiver class %s does not implement the requested interface %s",
 475                                            recv.getClass().getName(), refc.getName());
 476                 throw new IncompatibleClassChangeError(msg);
 477             }
 478             return recv;
 479         }
 480     }
 481 
 482     /** Used for interface receiver type checks, by Interface and Special modes. */
 483     Object checkReceiver(Object recv) {
 484         throw new InternalError("Should only be invoked on a subclass");
 485     }
 486 
 487 
 488     /** This subclass handles constructor references. */
 489     static class Constructor extends DirectMethodHandle {
 490         final MemberName initMethod;
 491         final Class<?>   instanceClass;
 492 
 493         private Constructor(MethodType mtype, LambdaForm form, MemberName constructor,
 494                             boolean crackable, MemberName initMethod, Class<?> instanceClass) {
 495             super(mtype, form, constructor, crackable);
 496             this.initMethod = initMethod;
 497             this.instanceClass = instanceClass;
 498             assert(initMethod.isResolved());
 499         }
 500         @Override
 501         MethodHandle copyWith(MethodType mt, LambdaForm lf) {
 502             return new Constructor(mt, lf, member, crackable, initMethod, instanceClass);
 503         }
 504         @Override
 505         MethodHandle viewAsType(MethodType newType, boolean strict) {
 506             assert viewAsTypeChecks(newType, strict);
 507             return new Constructor(newType, form, member, false, initMethod, instanceClass);
 508         }
 509     }
 510 
 511     /*non-public*/
 512     static Object constructorMethod(Object mh) {
 513         Constructor dmh = (Constructor)mh;
 514         return dmh.initMethod;
 515     }
 516 
 517     /*non-public*/
 518     static Object allocateInstance(Object mh) throws InstantiationException {
 519         Constructor dmh = (Constructor)mh;
 520         return UNSAFE.allocateInstance(dmh.instanceClass);
 521     }
 522 
 523     /** This subclass handles non-static field references. */
 524     static class Accessor extends DirectMethodHandle {
 525         final Class<?> fieldType;
 526         final int      fieldOffset;
 527         private Accessor(MethodType mtype, LambdaForm form, MemberName member,
 528                          boolean crackable, int fieldOffset) {
 529             super(mtype, form, member, crackable);
 530             this.fieldType   = member.getFieldType();
 531             this.fieldOffset = fieldOffset;
 532         }
 533 
 534         @Override Object checkCast(Object obj) {
 535             return fieldType.cast(obj);
 536         }
 537         @Override
 538         MethodHandle copyWith(MethodType mt, LambdaForm lf) {
 539             return new Accessor(mt, lf, member, crackable, fieldOffset);
 540         }
 541         @Override
 542         MethodHandle viewAsType(MethodType newType, boolean strict) {
 543             assert viewAsTypeChecks(newType, strict);
 544             return new Accessor(newType, form, member, false, fieldOffset);
 545         }
 546     }
 547 
 548     @ForceInline
 549     /*non-public*/
 550     static long fieldOffset(Object accessorObj) {
 551         // Note: We return a long because that is what Unsafe.getObject likes.
 552         // We store a plain int because it is more compact.
 553         return ((Accessor)accessorObj).fieldOffset;
 554     }
 555 
 556     @ForceInline
 557     /*non-public*/
 558     static Object checkBase(Object obj) {
 559         // Note that the object's class has already been verified,
 560         // since the parameter type of the Accessor method handle
 561         // is either member.getDeclaringClass or a subclass.
 562         // This was verified in DirectMethodHandle.make.
 563         // Therefore, the only remaining check is for null.
 564         // Since this check is *not* guaranteed by Unsafe.getInt
 565         // and its siblings, we need to make an explicit one here.
 566         return Objects.requireNonNull(obj);
 567     }
 568 
 569     /** This subclass handles static field references. */
 570     static class StaticAccessor extends DirectMethodHandle {
 571         private final Class<?> fieldType;
 572         private final Object   staticBase;
 573         private final long     staticOffset;
 574 
 575         private StaticAccessor(MethodType mtype, LambdaForm form, MemberName member,
 576                                boolean crackable, Object staticBase, long staticOffset) {
 577             super(mtype, form, member, crackable);
 578             this.fieldType    = member.getFieldType();
 579             this.staticBase   = staticBase;
 580             this.staticOffset = staticOffset;
 581         }
 582 
 583         @Override Object checkCast(Object obj) {
 584             return fieldType.cast(obj);
 585         }
 586         @Override
 587         MethodHandle copyWith(MethodType mt, LambdaForm lf) {
 588             return new StaticAccessor(mt, lf, member, crackable, staticBase, staticOffset);
 589         }
 590         @Override
 591         MethodHandle viewAsType(MethodType newType, boolean strict) {
 592             assert viewAsTypeChecks(newType, strict);
 593             return new StaticAccessor(newType, form, member, false, staticBase, staticOffset);
 594         }
 595     }
 596 
 597     @ForceInline
 598     /*non-public*/
 599     static Object nullCheck(Object obj) {
 600         return Objects.requireNonNull(obj);
 601     }
 602 
 603     @ForceInline
 604     /*non-public*/
 605     static Object staticBase(Object accessorObj) {
 606         return ((StaticAccessor)accessorObj).staticBase;
 607     }
 608 
 609     @ForceInline
 610     /*non-public*/
 611     static long staticOffset(Object accessorObj) {
 612         return ((StaticAccessor)accessorObj).staticOffset;
 613     }


< prev index next >