运行Java -jar somefile.jar时发生了什么(二)


(6)Java.c中的LoadMainClass

位置jdk/src/share/bin/java.c

该方法负责载入main函数所在的类。

该方法首先载入sun.launcher.LauncherHelper类,然后调用该类的checkAndLoadMain去找到main函数所在的类,相关代码例如以下。

jclass cls = GetLauncherHelperClass(env);//这个函数载入了sun.launcher.LauncherHelper类
    NULL_CHECK0(cls);
    if (JLI_IsTraceLauncher()) {
        start = CounterGet();
    }
    NULL_CHECK0(mid = (*env)->GetStaticMethodID(env, cls,//找到方法id
                "checkAndLoadMain",
                "(ZILjava/lang/String;)Ljava/lang/Class;"));

    str = NewPlatformString(env, name);
    result = (*env)->CallStaticObjectMethod(env, cls, mid, USE_STDERR, mode, str);//调用这个静态方法


(7)LauncherHelper.java中的checkAndLoadMain

位置:jdk/src/share/bin/classes/sun/launcher/LauncherHelper.java

Java代码比較直观。我就直接写凝视了

</pre><p><pre name="code" class="java"> public static Class<?

> checkAndLoadMain(boolean printToStderr, int mode, String what) { initOutput(printToStderr); // mode决定是直接传入的主类还是jar文件。即区分java -jar xxx.jar 还是 java xxx.class String cn = null; switch (mode) { case LM_CLASS: cn = what; break; case LM_JAR: cn = getMainClassFromJar(what);//这个函数的原理是抽取jar中的mainfest文件得到其主类 break; default: // should never happen throw new InternalError("" + mode + ": Unknown launch mode"); } cn = cn.replace('/', '.'); Class<?> mainClass = null; try { mainClass = scloader.loadClass(cn);//使用scloader载入,怎样载入水比較深。这里就不展开说了。

} catch (NoClassDefFoundError | ClassNotFoundException cnfe) { if (System.getProperty("os.name", "").contains("OS X") && Normalizer.isNormalized(cn, Normalizer.Form.NFD)) { try { // On Mac OS X since all names with diacretic symbols are given as decomposed it // is possible that main class name comes incorrectly from the command line // and we have to re-compose it mainClass = scloader.loadClass(Normalizer.normalize(cn, Normalizer.Form.NFC)); } catch (NoClassDefFoundError | ClassNotFoundException cnfe1) { abort(cnfe, "java.launcher.cls.error1", cn); } } else { abort(cnfe, "java.launcher.cls.error1", cn); } } // set to mainClass appClass = mainClass; /* * Check if FXHelper can launch it using the FX launcher. In an FX app, * the main class may or may not have a main method, so do this before * validating the main class. */ if (mainClass.equals(FXHelper.class) || FXHelper.doesExtendFXApplication(mainClass)) { // Will abort() if there are problems with the FX runtime FXHelper.setFXLaunchParameters(what, mode); return FXHelper.class; } validateMainClass(mainClass);//这里对主类有效性即可了验证,代码附在后面。 return mainClass; }



 
  接下来给出了验证主类是否有效的代码。 
  

static void validateMainClass(Class<?> mainClass) {
        Method mainMethod;
        try {
            mainMethod = mainClass.getMethod("main", String[].class);//看看是否存在例如以下签名的方法 main(String[] argvs)
        } catch (NoSuchMethodException nsme) {
            // invalid main or not FX application, abort with an error
            abort(null, "java.launcher.cls.error4", mainClass.getName(),
                  FXHelper.JAVAFX_APPLICATION_CLASS_NAME);
            return; // Avoid compiler issues
        }


        int mod = mainMethod.getModifiers();//取得限定符
        if (!Modifier.isStatic(mod)) {//假设不是static的则报错
            abort(null, "java.launcher.cls.error2", "static",
                  mainMethod.getDeclaringClass().getName());
        }
        if (mainMethod.getReturnType() != java.lang.Void.TYPE) {
            abort(null, "java.launcher.cls.error3",//假设不是void的也报错
                  mainMethod.getDeclaringClass().getName());
        }
    }


二、总结


这两篇博客主要分析了运行java命令详细会发生一些什么事情,通过阅读代码能够了解到配置的环境变量怎样起作用。jvm何时初始化。以及主类载入及验证过程。


本片博客起码还有下面几点没有深入的分析到:

jvm怎样初始化。

env结构和vm结构的关系及实现。

scloader怎么作用。

LauncherHelper怎样载入。

这些问题也许会在后面的博客进行分析。


转载于:https://www.cnblogs.com/liguangsunls/p/6860084.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值