在jdk9之前,Java 项目由一堆 JAR 包组成,而每个jar包里面都会有单独的多个class文件,这些class文件分为两种,一种是用户开发自己项目的class,一种是导入各种依赖的class,JVM并不关系JAR包之间的关系,他仅仅只是用来包装class文件的,而JVM也只负责把他们的class文件放入classpath中。这时候一旦漏传了某个依赖JAR,程序在运行时就会抛出ClassNotFoundException报错
// class is public and package is exported to caller //如果类是public公共类并且包被exported给调用者 booleanisClassPublic= Modifier.isPublic(declaringClass.getModifiers()); if (isClassPublic && declaringModule.isExported(pn, callerModule)) { // member is public //如果成员是public属性直接返回true if (Modifier.isPublic(modifiers)) { returntrue; }
// member is protected-static //如果成员是protected和static,并且调用者类是被调用类的子类,则返回true if (Modifier.isProtected(modifiers) && Modifier.isStatic(modifiers) && isSubclassOf(caller, declaringClass)) { returntrue; } }
// package is open to caller //如果包被open给调用者,直接返回true if (declaringModule.isOpen(pn, callerModule)) { returntrue; }
if (throwExceptionIfDenied) { // not accessible Stringmsg="Unable to make "; if (thisinstanceof Field) msg += "field "; msg += this + " accessible: " + declaringModule + " does not \""; if (isClassPublic && Modifier.isPublic(modifiers)) msg += "exports"; else msg += "opens"; msg += " " + pn + "\" to " + callerModule; InaccessibleObjectExceptione=newInaccessibleObjectException(msg); if (printStackTraceWhenAccessFails()) { e.printStackTrace(System.err); } throw e; } returnfalse; }
@ForceInline publiclongobjectFieldOffset(Field f) { if (f == null) { thrownewNullPointerException(); } Class<?> declaringClass = f.getDeclaringClass(); if (declaringClass.isHidden()) { thrownewUnsupportedOperationException("can't get field offset on a hidden class: " + f); } if (declaringClass.isRecord()) { thrownewUnsupportedOperationException("can't get field offset on a record class: " + f); } return theInternalUnsafe.objectFieldOffset(f); }
传入一个反射的 Field 对象(非静态字段),会返回该字段在对象内存布局中的偏移量 (offset)
sun.misc.Unsafe#staticFieldOffset()
1 2 3 4 5 6 7 8 9 10 11 12 13 14
@ForceInline publiclongstaticFieldOffset(Field f) { if (f == null) { thrownewNullPointerException(); } Class<?> declaringClass = f.getDeclaringClass(); if (declaringClass.isHidden()) { thrownewUnsupportedOperationException("can't get field offset on a hidden class: " + f); } if (declaringClass.isRecord()) { thrownewUnsupportedOperationException("can't get field offset on a record class: " + f); } return theInternalUnsafe.staticFieldOffset(f); }
返回静态字段的内存偏移值offet
sun.misc.Unsafe#getObject()
1 2 3 4
@ForceInline public Object getObject(Object o, long offset) { return theInternalUnsafe.getReference(o, offset); }
根据对象和偏移值获取到该地址处存放的 对象引用
sun.misc.Unsafe#staticFieldBase()
1 2 3 4 5 6 7 8 9 10 11 12 13 14
@ForceInline public Object staticFieldBase(Field f) { if (f == null) { thrownewNullPointerException(); } Class<?> declaringClass = f.getDeclaringClass(); if (declaringClass.isHidden()) { thrownewUnsupportedOperationException("can't get base address on a hidden class: " + f); } if (declaringClass.isRecord()) { thrownewUnsupportedOperationException("can't get base address on a record class: " + f); } return theInternalUnsafe.staticFieldBase(f); }