Life is too short to have a dog

One, foreword

I don’t know if all of you are like me. The first code you wrote when you first learned Java was something like the following code:

    public static void main(String[] args) {
        System.out.println("hello, world!");
    }
Copy the code

The above code simply prints “Hell, world!” in the console. This sentence. Of course, today’s focus is not on what this code does, but on where this code appears, which is the main function.

2. Everything begins with main

If you look back at any code you’ve ever written, whether it’s a complex microservice project or a simple line of system.out.println (), the entry function to the code must be the main function. But as a programmer with a dream, you need to know how and why to do things, so let’s explore why everything starts with main.

1. Why main

As we all know, Java files are written to run on the JVM, that is, programs are compiled and run according to the JVM’s rules, so let’s take a look at the JVM source code.

The JVM launcher defines a method int JNICALL JavaMain(void * args); This method determines how to load the entry classes and methods of a Java application. Here we omit the rest of the code and go straight to the code that loads the entry methods:

    /* Get the main */ of the application
    mainID = (*env)->GetStaticMethodID(env, mainClass, "main"."([Ljava/lang/String;)V");
    if (mainID == NULL) {
        if ((*env)->ExceptionOccurred(env)) {
            ReportExceptionDescription(env);
        } else {
          message = "No main method found in specified class.";
          messageDest = JNI_TRUE;
        }
        goto leave;
    }

    {    /* Make sure the main method is public */
        jint mods;
        jmethodID mid;
        jobject obj = (*env)->ToReflectedMethod(env, mainClass,
                                                mainID, JNI_TRUE);

        if( obj == NULL) { /* Throws an exception */
            ReportExceptionDescription(env);
            goto leave;
        }

        mid =
          (*env)->GetMethodID(env,
                              (*env)->GetObjectClass(env, obj),
                              "getModifiers"."()I");
        if ((*env)->ExceptionOccurred(env)) {
            ReportExceptionDescription(env);
            goto leave;
        }

        mods = (*env)->CallIntMethod(env, obj, mid);
        if ((mods & 1) = =0) { /* if (! Modifier.isPublic(mods)) ... * /
            message = "Main method not public.";
            messageDest = JNI_TRUE;
            gotoleave; }}/* Build argument array */
    mainArgs = NewPlatformStringArray(env, argv, argc);
    if (mainArgs == NULL) {
        ReportExceptionDescription(env);
        goto leave;
    }

    /* Execute the main method */
    (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);
Copy the code

As you can see in the above code, the JVM gets the main method from the specified MainClass class during startup. It also specifies that the main method must be static, public, and the argument list must be a String array. This should help you understand why the entry function must be main when writing Java programs.

2. How to execute the main function

Now that we know why the entry method of a Java program must be main, let’s take a look at how a Java program that contains main is executed.

When we execute the above code in idea, we actually execute the following command:

Java {class name}.javaCopy the code

The Java instructions that appear in the above command line are actually instructions provided by the JDK to execute Java programs, and the file name immediately following the instructions is the Java program to execute. This command will start the Java exec such an executable program, in the executable program executes the SRC/share/tools/the launcher/Java. The main method of c file, Perform a runtime version check before JVM startup, configure initialization, and create a JVM process to execute the Java program, which finds and calls the main method of the entry class as shown in the code above.

Note that the JVM executes a Java program as a.class file that has already been compiled, which means that the javac instruction is executed on the.java file where the instruction is executed, and then the above operation is performed. This can also be seen in the code above that gets the main method in the Java program:

mainID = (*env)->GetStaticMethodID(env, mainClass, "main"."([Ljava/lang/String;)V");
Copy the code

The parameter list is written in the compiled binary. Class file. If you are interested, you can check the binary file by using the tool provided with IDEA.

The logic that follows is the familiar process by which the JVM loads, links, and initializes classes and interfaces, without going into too much detail here.

3. How Java programs are executed

In the daily development process, in addition to the above directly run a Java file, we are mostly the Java program packaged into a JAR package to run, here from the source code can also get a glimpse of one or two.

    if(jarfile ! =0) {
      // If you run in jar mode, get mainClass from the corresponding JAR
        mainClassName = GetMainClassName(env, jarfile);
        if ((*env)->ExceptionOccurred(env)) {
            ReportExceptionDescription(env);
            goto leave;
        }
        if (mainClassName == NULL) {
          const char * format = "Failed to load Main-Class manifest "
                                "attribute from\n%s";
          message = (char*)JLI_MemAlloc((strlen(format) + strlen(jarfile)) *
                                    sizeof(char));
          sprintf(message, format, jarfile);
          messageDest = JNI_TRUE;
          goto leave;
        }
        classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0);
        if (classname == NULL) {
            ReportExceptionDescription(env);
            goto leave;
        }
        mainClass = LoadClass(env, classname);
        if(mainClass == NULL) { /* exception occured */
            const char * format = "Could not find the main class: %s. Program will exit.";
            ReportExceptionDescription(env);
            message = (char *)JLI_MemAlloc((strlen(format) +
                                            strlen(classname)) * sizeof(char)); messageDest = JNI_TRUE;sprintf(message, format, classname);
            goto leave;
        }
        (*env)->ReleaseStringUTFChars(env, mainClassName, classname);
    } else {
      // Specify the className of the entry mainClass directly
      mainClassName = NewPlatformString(env, classname);
      if (mainClassName == NULL) {
        const char * format = "Failed to load Main Class: %s";
        message = (char *)JLI_MemAlloc((strlen(format) + strlen(classname)) *
                                   sizeof(char));sprintf(message, format, classname);
        messageDest = JNI_TRUE;
        goto leave;
      }
      classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0);
      if (classname == NULL) {
        ReportExceptionDescription(env);
        goto leave;
      }
      mainClass = LoadClass(env, classname);
      if(mainClass == NULL) { /* exception occured */
        const char * format = "Could not find the main class: %s. Program will exit.";
        ReportExceptionDescription(env);
        message = (char *)JLI_MemAlloc((strlen(format) +
                                        strlen(classname)) * sizeof(char)); messageDest = JNI_TRUE;sprintf(message, format, classname);
        goto leave;
      }
      (*env)->ReleaseStringUTFChars(env, mainClassName, classname);
    }
Copy the code

As you can see from the above code, the Main Class of the application can be obtained either by getting the main-class name specified in the META-INF/ manifest.mf file in the JAR package, or by specifying a className (as in the above example).

Third, summary

Whim reviewed once again at the beginning only know its then do not know its why knowledge point, analysis does not necessarily reach the specified position, for everyone reference only. The JDK source code used in the above analysis is based on the openJDK official website provided by hotspot 1.7 version of the source code, interested students can download the source code on the official website to read and learn.