System源码浅析- initializeSystemClass(loadLibrary)

本文深入探讨了Java中System类的loadLibrary方法,详细解析了从loadLibrary0开始,经过getCallerClass、JVM_GetCallerClass等一系列安全检查和权限验证的过程,直至最终的库加载步骤。
摘要由CSDN通过智能技术生成

前情提要

在前面已经介绍过 System与initializeSystemClass 在此不做过多解释,没有看到的希望去查看!
System源码浅析- initializeSystemClass(initProperties)
System源码浅析- initializeSystemClass(saveAndRemoveProperties)
System源码浅析- initializeSystemClass(setXXX0)
System源码浅析- initializeSystemClass(loadLibrary)
System源码浅析- initializeSystemClass(setup)
System源码浅析- initializeSystemClass( initializeOSEnvironment )
System源码浅析- initializeSystemClass( setJavaLangAccess)

loadLibrary

/**
	加载由 <code>libname<code> 参数指定的本机库。
     <code>libname<code> 参数不得包含任何特定于平台的前缀、文件扩展名或路径。
     如果名为 <code>libname<code> 的本机库与 VM 静态链接,
     则调用该库导出的 JNI_OnLoad_<code>libname<code> 函数。有关更多详细信息,
     请参阅 JNI 规范。
     否则,libname 参数将从系统库位置加载并以与实现相关的方式映射到本机库映像。
*/
@CallerSensitive
public static void loadLibrary(String libname) {
   
    Runtime.getRuntime().loadLibrary0(Reflection.getCallerClass(), libname);
}

loadLibrary0

// fromClass 调用者
synchronized void loadLibrary0(Class<?> fromClass, String libname) {
   
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
   
        security.checkLink(libname);
    }
    if (libname.indexOf((int)File.separatorChar) != -1) {
   
        throw new UnsatisfiedLinkError(
"Directory separator should not appear in library name: " + libname);
    }
    ClassLoader.loadLibrary(fromClass, libname, false);
}

getCallerClass

@CallerSensitive
public static native Class<?> getCallerClass();

Java_sun_reflect_Reflection_getCallerClass__

JNIEXPORT jclass JNICALL Java_sun_reflect_Reflection_getCallerClass__
(JNIEnv *env, jclass unused)
{
   
    /*
	返回调用 JVM_GetCallerClass 的本机方法的直接调用者类。由于反射机制,Method.invoke 和其他帧被跳过。
	深度参数必须为 -1 (JVM_DEPTH)。调用者应该被标记为 sun.reflect.CallerSensitive。如果没有正确标记,JVM 将抛出错误	
    JVM_GetCallerClass(JNIEnv *env, int depth);
    /
    return JVM_GetCallerClass(env, JVM_CALLER_DEPTH);
}

JVM_GetCallerClass

// 返回调用者
JVM_ENTRY(jclass, JVM_GetCallerClass(JNIEnv* env, int depth))
  JVMWrapper("JVM_GetCallerClass");

  //JDK 8 之前的版本和 JDK 8 的早期版本没有 CallerSensitive 注释;或带有深度参数的 sun.reflect.Reflection.getCallerClass 临时提供给现有代码使用,直到定义替换 API。
  if (SystemDictionary::reflect_CallerSensitive_klass() == NULL || depth != JVM_CALLER_DEPTH) {
   
      // 返回“深度”的方法 java 或栈中的原生帧 用于安全检查
    Klass* k = thread->security_get_caller_class(depth);
    return (k == NULL) ? NULL : (jclass) JNIHandles::make_local(env, k->java_mirror());
  }

  // 获取调用者框架的类
  //
  // 此时的调用堆栈如下所示:
  //
  // [0] [ @CallerSensitive public sun.reflect.Reflection.getCallerClass ]
  // [1] [ @CallerSensitive API.method                                   ]
  // [.] [ (skipped intermediate frames)                                 ]
  // [n] [ caller                                                        ]
  vframeStream vfst(thread);
  // Cf. LibraryCallKit::inline_native_Reflection_getCallerClass
  for (int n = 0; !vfst.at_end(); vfst.security_next(), n++) {
   
    Method* m = vfst.method();
    assert(m != NULL, "sanity");
    switch (n) {
   
    case 0:
      // 这只能从 Reflection.getCallerClass 调用
      if (m->intrinsic_id() != vmIntrinsics::_getCallerClass) {
   
        THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "JVM_GetCallerClass must only be called from Reflection.getCallerClass");
      }
      // fall-through
    case 1:
      // Frame 0 和 1 必须是调用者sensitive.
      if (!m->caller_sensitive()) {
   
        THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), err_msg("CallerSensitive annotation expected at frame %d", n));
      }
      break;
    default:
      if (!m->is_ignored_by_security_stack_walk()) {
   
        // 我们已经达到了预期的框架;返回持有者类。
        return (jclass) JNIHandles::make_local(env, m->method_holder()->java_mirror());
      }
      break;
    }
  }
  return NULL;
JVM_END

security_get_caller_class

Klass* JavaThread::security_get_caller_class(int depth) {
   
  vframeStream vfst(this);
  // 后退 n 帧,跳过其间的任何伪帧。该函数用于Class.forName、Class.newInstance、Method.Invoke、AccessController.doPrivileged。
  vfst.security_get_caller_frame(depth);
  if (!vfst.at_end()) {
   
    return vfst.method()-><
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值