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

本文详细剖析了执行java命令时的内部运作机制,包括环境变量的作用、JVM的初始化、主类的加载与验证过程。同时指出了一些关键点如JVM初始化、env与vm结构的关系、scloader的作用以及LauncherHelper的加载方式并未深入分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


(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如何加载。

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


sbt:spark-app> assembly [warn] multiple main classes detected: run 'show discoveredMainClasses' to see the list [error] 37 error(s) were encountered during the merge: [error] stack trace is suppressed; run last assembly for the full output [error] (assembly) [error] Deduplicate found different file contents in the following: [error] Jar name = protobuf-java-3.19.6.jar, jar org = com.google.protobuf, entry target = google/protobuf/api.proto [error] Jar name = spark-core_2.12-3.5.0.jar, jar org = org.apache.spark, entry target = google/protobuf/api.proto [error] Deduplicate found different file contents in the following: [error] Jar name = protobuf-java-3.19.6.jar, jar org = com.google.protobuf, entry target = google/protobuf/field_mask.proto [error] Jar name = spark-core_2.12-3.5.0.jar, jar org = org.apache.spark, entry target = google/protobuf/field_mask.proto [error] Deduplicate found different file contents in the following: [error] Jar name = commons-logging-1.1.3.jar, jar org = commons-logging, entry target = org/apache/commons/logging/Log.class [error] Jar name = jcl-over-slf4j-2.0.7.jar, jar org = org.slf4j, entry target = org/apache/commons/logging/Log.class [error] Deduplicate found different file contents in the following: [error] Jar name = protobuf-java-3.19.6.jar, jar org = com.google.protobuf, entry target = google/protobuf/struct.proto [error] Jar name = spark-core_2.12-3.5.0.jar, jar org = org.apache.spark, entry target = google/protobuf/struct.proto [error] Deduplicate found different file contents in the following: [error] Jar name = commons-logging-1.1.3.jar, jar org = commons-logging, entry target = org/apache/commons/logging/impl/NoOpLog.class [error] Jar name = jcl-over-slf4j-2.0.7.jar, jar org = org.slf4j, entry target = org/apache/commons/logging/impl/NoOpLog.class [error] Deduplicate found different file contents in the following: [error] Jar name = arrow-format-11.0.0.jar, jar org = org.apache.arrow, entry target = arrow-git.properties [error] Jar name = arrow-memory-core-11.0.0.jar, jar org = org.apache.arrow, entry target = arrow-git.properties [error] Jar name = arrow-memory-netty-11.0.0.jar, jar org = org.apache.arrow, entry target = arrow-git.properties [error] Jar name = arrow-vector-11.0.0.jar, jar org = org.apache.arrow, entry target = arrow-git.properties [error] Deduplicate found different file contents in the following: [error] Jar name = javax.inject-1.jar, jar org = javax.inject, entry target = javax/inject/Singleton.class [error] Jar name = jakarta.inject-2.6.1.jar, jar org = org.glassfish.hk2.external, entry target = javax/inject/Singleton.class [error] Deduplicate found different file contents in the following: [error] Jar name = protobuf-java-3.19.6.jar, jar org = com.google.protobuf, entry target = google/protobuf/duration.proto [error] Jar name = spark-core_2.12-3.5.0.jar, jar org = org.apache.spark, entry target = google/protobuf/duration.proto [error] Deduplicate found different file contents in the following: [error] Jar name = javax.inject-1.jar, jar org = javax.inject, entry target = javax/inject/Named.class [error] Jar name = jakarta.inject-2.6.1.jar, jar org = org.glassfish.hk2.external, entry target = javax/inject/Named.class [error] Deduplicate found different file contents in the following: [error] Jar name = javax.inject-1.jar, jar org = javax.inject, entry target = javax/inject/Inject.class [error] Jar name = jakarta.inject-2.6.1.jar, jar org = org.glassfish.hk2.external, entry target = javax/inject/Inject.class [error] Deduplicate found different file contents in the following: [error] Jar name = commons-logging-1.1.3.jar, jar org = commons-logging, entry target = org/apache/commons/logging/LogFactory.class [error] Jar name = jcl-over-slf4j-2.0.7.jar, jar org = org.slf4j, entry target = org/apache/commons/logging/LogFactory.class [error] Deduplicate found different file contents in the following: [error] Jar name = commons-logging-1.1.3.jar, jar org = commons-logging, entry target = org/apache/commons/logging/LogConfigurationException.class [error] Jar name = jcl-over-slf4j-2.0.7.jar, jar org = org.slf4j, entry target = org/apache/commons/logging/LogConfigurationException.class [error] Deduplicate found different file contents in the following: [error] Jar name = jakarta.annotation-api-1.3.5.jar, jar org = jakarta.annotation, entry target = javax/annotation/security/DenyAll.class [error] Jar name = jsr250-api-1.0.jar, jar org = javax.annotation, entry target = javax/annotation/security/DenyAll.class [error] Deduplicate found different file contents in the following: [error] Jar name = protobuf-java-3.19.6.jar, jar org = com.google.protobuf, entry target = google/protobuf/timestamp.proto [error] Jar name = spark-core_2.12-3.5.0.jar, jar org = org.apache.spark, entry target = google/protobuf/timestamp.proto [error] Deduplicate found different file contents in the following: [error] Jar name = jakarta.annotation-api-1.3.5.jar, jar org = jakarta.annotation, entry target = javax/annotation/Generated.class [error] Jar name = jsr250-api-1.0.jar, jar org = javax.annotation, entry target = javax/annotation/Generated.class [error] Deduplicate found different file contents in the following: [error] Jar name = protobuf-java-3.19.6.jar, jar org = com.google.protobuf, entry target = google/protobuf/source_context.proto [error] Jar name = spark-core_2.12-3.5.0.jar, jar org = org.apache.spark, entry target = google/protobuf/source_context.proto [error] Deduplicate found different file contents in the following: [error] Jar name = protobuf-java-3.19.6.jar, jar org = com.google.protobuf, entry target = google/protobuf/empty.proto [error] Jar name = spark-core_2.12-3.5.0.jar, jar org = org.apache.spark, entry target = google/protobuf/empty.proto [error] Deduplicate found different file contents in the following: [error] Jar name = jakarta.annotation-api-1.3.5.jar, jar org = jakarta.annotation, entry target = javax/annotation/Resource.class [error] Jar name = jsr250-api-1.0.jar, jar org = javax.annotation, entry target = javax/annotation/Resource.class [error] Deduplicate found different file contents in the following: [error] Jar name = jakarta.annotation-api-1.3.5.jar, jar org = jakarta.annotation, entry target = javax/annotation/security/RolesAllowed.class [error] Jar name = jsr250-api-1.0.jar, jar org = javax.annotation, entry target = javax/annotation/security/RolesAllowed.class [error] Deduplicate found different file contents in the following: [error] Jar name = jakarta.annotation-api-1.3.5.jar, jar org = jakarta.annotation, entry target = javax/annotation/PreDestroy.class [error] Jar name = jsr250-api-1.0.jar, jar org = javax.annotation, entry target = javax/annotation/PreDestroy.class [error] Deduplicate found different file contents in the following: [error] Jar name = protobuf-java-3.19.6.jar, jar org = com.google.protobuf, entry target = google/protobuf/descriptor.proto [error] Jar name = spark-core_2.12-3.5.0.jar, jar org = org.apache.spark, entry target = google/protobuf/descriptor.proto [error] Deduplicate found different file contents in the following: [error] Jar name = commons-logging-1.1.3.jar, jar org = commons-logging, entry target = org/apache/commons/logging/impl/SimpleLog.class [error] Jar name = jcl-over-slf4j-2.0.7.jar, jar org = org.slf4j, entry target = org/apache/commons/logging/impl/SimpleLog.class [error] Deduplicate found different file contents in the following: [error] Jar name = jakarta.annotation-api-1.3.5.jar, jar org = jakarta.annotation, entry target = javax/annotation/security/DeclareRoles.class [error] Jar name = jsr250-api-1.0.jar, jar org = javax.annotation, entry target = javax/annotation/security/DeclareRoles.class [error] Deduplicate found different file contents in the following: [error] Jar name = protobuf-java-3.19.6.jar, jar org = com.google.protobuf, entry target = google/protobuf/wrappers.proto [error] Jar name = spark-core_2.12-3.5.0.jar, jar org = org.apache.spark, entry target = google/protobuf/wrappers.proto [error] Deduplicate found different file contents in the following: [error] Jar name = javax.inject-1.jar, jar org = javax.inject, entry target = javax/inject/Qualifier.class [error] Jar name = jakarta.inject-2.6.1.jar, jar org = org.glassfish.hk2.external, entry target = javax/inject/Qualifier.class [error] Deduplicate found different file contents in the following: [error] Jar name = jakarta.annotation-api-1.3.5.jar, jar org = jakarta.annotation, entry target = javax/annotation/security/PermitAll.class [error] Jar name = jsr250-api-1.0.jar, jar org = javax.annotation, entry target = javax/annotation/security/PermitAll.class [error] Deduplicate found different file contents in the following: [error] Jar name = protobuf-java-3.19.6.jar, jar org = com.google.protobuf, entry target = google/protobuf/any.proto [error] Jar name = spark-core_2.12-3.5.0.jar, jar org = org.apache.spark, entry target = google/protobuf/any.proto [error] Deduplicate found different file contents in the following: [error] Jar name = jakarta.annotation-api-1.3.5.jar, jar org = jakarta.annotation, entry target = javax/annotation/Resources.class [error] Jar name = jsr250-api-1.0.jar, jar org = javax.annotation, entry target = javax/annotation/Resources.class [error] Deduplicate found different file contents in the following: [error] Jar name = jakarta.annotation-api-1.3.5.jar, jar org = jakarta.annotation, entry target = javax/annotation/Resource$AuthenticationType.class [error] Jar name = jsr250-api-1.0.jar, jar org = javax.annotation, entry target = javax/annotation/Resource$AuthenticationType.class [error] Deduplicate found different file contents in the following: [error] Jar name = jackson-core-2.15.2.jar, jar org = com.fasterxml.jackson.core, entry target = META-INF/versions/9/module-info.class [error] Jar name = jackson-databind-2.15.2.jar, jar org = com.fasterxml.jackson.core, entry target = META-INF/versions/9/module-info.class [error] Jar name = jackson-datatype-jsr310-2.13.4.jar, jar org = com.fasterxml.jackson.datatype, entry target = META-INF/versions/9/module-info.class [error] Jar name = gson-2.10.1.jar, jar org = com.google.code.gson, entry target = META-INF/versions/9/module-info.class [error] Jar name = log4j-api-2.20.0.jar, jar org = org.apache.logging.log4j, entry target = META-INF/versions/9/module-info.class [error] Jar name = parquet-jackson-1.12.3.jar, jar org = org.apache.parquet, entry target = META-INF/versions/9/module-info.class [error] Jar name = jcl-over-slf4j-2.0.7.jar, jar org = org.slf4j, entry target = META-INF/versions/9/module-info.class [error] Jar name = slf4j-api-2.0.7.jar, jar org = org.slf4j, entry target = META-INF/versions/9/module-info.class [error] Jar name = xz-1.9.jar, jar org = org.tukaani, entry target = META-INF/versions/9/module-info.class [error] Deduplicate found different file contents in the following: [error] Jar name = protobuf-java-3.19.6.jar, jar org = com.google.protobuf, entry target = google/protobuf/type.proto [error] Jar name = spark-core_2.12-3.5.0.jar, jar org = org.apache.spark, entry target = google/protobuf/type.proto [error] Deduplicate found different file contents in the following: [error] Jar name = jakarta.annotation-api-1.3.5.jar, jar org = jakarta.annotation, entry target = javax/annotation/PostConstruct.class [error] Jar name = jsr250-api-1.0.jar, jar org = javax.annotation, entry target = javax/annotation/PostConstruct.class [error] Deduplicate found different file contents in the following: [error] Jar name = netty-all-4.1.96.Final.jar, jar org = io.netty, entry target = META-INF/io.netty.versions.properties [error] Jar name = netty-buffer-4.1.96.Final.jar, jar org = io.netty, entry target = META-INF/io.netty.versions.properties [error] Jar name = netty-codec-http2-4.1.96.Final.jar, jar org = io.netty, entry target = META-INF/io.netty.versions.properties [error] Jar name = netty-codec-http-4.1.96.Final.jar, jar org = io.netty, entry target = META-INF/io.netty.versions.properties [error] Jar name = netty-codec-socks-4.1.96.Final.jar, jar org = io.netty, entry target = META-INF/io.netty.versions.properties [error] Jar name = netty-codec-4.1.96.Final.jar, jar org = io.netty, entry target = META-INF/io.netty.versions.properties [error] Jar name = netty-common-4.1.96.Final.jar, jar org = io.netty, entry target = META-INF/io.netty.versions.properties [error] Jar name = netty-handler-proxy-4.1.96.Final.jar, jar org = io.netty, entry target = META-INF/io.netty.versions.properties [error] Jar name = netty-handler-4.1.96.Final.jar, jar org = io.netty, entry target = META-INF/io.netty.versions.properties [error] Jar name = netty-resolver-4.1.96.Final.jar, jar org = io.netty, entry target = META-INF/io.netty.versions.properties [error] Jar name = netty-transport-classes-epoll-4.1.96.Final.jar, jar org = io.netty, entry target = META-INF/io.netty.versions.properties [error] Jar name = netty-transport-classes-kqueue-4.1.96.Final.jar, jar org = io.netty, entry target = META-INF/io.netty.versions.properties [error] Jar name = netty-transport-native-epoll-4.1.96.Final.jar, jar org = io.netty, entry target = META-INF/io.netty.versions.properties [error] Jar name = netty-transport-native-epoll-4.1.96.Final.jar, jar org = io.netty, entry target = META-INF/io.netty.versions.properties [error] Jar name = netty-transport-native-epoll-4.1.96.Final.jar, jar org = io.netty, entry target = META-INF/io.netty.versions.properties [error] Jar name = netty-transport-native-kqueue-4.1.96.Final.jar, jar org = io.netty, entry target = META-INF/io.netty.versions.properties [error] Jar name = netty-transport-native-kqueue-4.1.96.Final.jar, jar org = io.netty, entry target = META-INF/io.netty.versions.properties [error] Jar name = netty-transport-native-unix-common-4.1.96.Final.jar, jar org = io.netty, entry target = META-INF/io.netty.versions.properties [error] Jar name = netty-transport-4.1.96.Final.jar, jar org = io.netty, entry target = META-INF/io.netty.versions.properties [error] Deduplicate found different file contents in the following: [error] Jar name = javax.inject-1.jar, jar org = javax.inject, entry target = javax/inject/Scope.class [error] Jar name = jakarta.inject-2.6.1.jar, jar org = org.glassfish.hk2.external, entry target = javax/inject/Scope.class [error] Deduplicate found different file contents in the following: [error] Jar name = log4j-1.2-api-2.20.0.jar, jar org = org.apache.logging.log4j, entry target = META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat [error] Jar name = log4j-core-2.20.0.jar, jar org = org.apache.logging.log4j, entry target = META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat [error] Deduplicate found different file contents in the following: [error] Jar name = javax.inject-1.jar, jar org = javax.inject, entry target = javax/inject/Provider.class [error] Jar name = jakarta.inject-2.6.1.jar, jar org = org.glassfish.hk2.external, entry target = javax/inject/Provider.class [error] Deduplicate found different file contents in the following: [error] Jar name = jakarta.annotation-api-1.3.5.jar, jar org = jakarta.annotation, entry target = javax/annotation/security/RunAs.class [error] Jar name = jsr250-api-1.0.jar, jar org = javax.annotation, entry target = javax/annotation/security/RunAs.class [error] Total time: 5 s, completed 2025年7月12日 下午12:56:20 [error] server failed to start on local:sbt-server-8814d8f5c3747ce114fe. java.io.IOException: Could not create lock for \\.\pipe\sbt-server-8814d8f5c3747ce114fe_lock, error 5 sbt:spark-app>
07-13
org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate component class: file [E:\BJJGSWGLJ\hd\wisdom-city-common\target\classes\com\louddt\asset\wisdom\entity\common\dict\Dict.class]; nested exception is org.springframework.core.NestedIOException: ASM ClassReader failed to parse class file - probably due to a new Java class file version that isn't supported yet: file [E:\BJJGSWGLJ\hd\wisdom-city-common\target\classes\com\louddt\asset\wisdom\entity\common\dict\Dict.class]; nested exception is java.lang.IllegalArgumentException: Unsupported class file major version 61 at org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.scanCandidateComponents(ClassPathScanningCandidateComponentProvider.java:452) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE] at org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.findCandidateComponents(ClassPathScanningCandidateComponentProvider.java:315) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE] at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:276) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE] at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:132) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE] at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:296) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE] at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:250) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE] at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:207) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE] at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationCl
最新发布
08-01
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值