jamVM阅读(一)——解析参数

本文从jamVM的源码入手,探讨如何解析命令行参数。通过阅读源码,了解jamVM如何处理class或jar文件,验证参数合法性,并解析java命令的各类参数。文章着重讲解parseCommandLine函数,该函数将参数赋值到全局变量args,为后续的执行流程做准备。
摘要由CSDN通过智能技术生成

学习源码,是代码技术提升的一个重要手段,在java相关的内容中,有各类框架的源码、tomcat的源码、android源码、jdk标准库的源码和jvm的源码等各种值得学习的内容。在这些内容当中,jvm的源码是唯一一种纯用c、c++完成的,因此对于很多写习惯了java的程序员来说,阅读jvm是一件不那么容易的事情,而且目前大多数的jvm源码相当冗长,不易于阅读,所以为了简单的了解jvm的运行机制,我们选择了“麻雀虽小,五脏俱全”的jamvm来进行阅读。

首先,下载编译jamvm自行百度去,这篇文章只对jamvm的代码做简单理解

由于对jamvm还不是特别了解,我们简单地从主函数开始进行阅读

int main(int argc, char *argv[]) {
    Class *array_class, *main_class;
    Object *system_loader, *array;
    MethodBlock *mb;
    InitArgs args;
    int class_arg;
    char *cpntr;
    int status;
    int i;

    setDefaultInitArgs(&args);

    // 解析命令参数
    class_arg = parseCommandLine(argc, argv, &args);

    // 设置类栈
    args.main_stack_base = &array_class;


    if (!initVM(&args)) {
        /**
         * TODO: Read
         * 启动虚拟机, 失败打印
         */
        printf("Could not initialise VM.  Aborting.\n");
        exit(1);
    }

    if ((system_loader = getSystemClassLoader()) == NULL)
        // TODO 设置主classLoader
        goto error;

    // TODO 给主线程设置classLoader
    mainThreadSetContextClassLoader(system_loader);

    for (cpntr = argv[class_arg]; *cpntr; cpntr++)
        /**
         * 把class的参数, 如‘jamVM HelloWorld’的‘HelloWorld’赋值给cpntr,对于路径修改为斜杠
         */
        if (*cpntr == '.')
            *cpntr = '/';


    // TODO 查询主函数
    main_class = findClassFromClassLoader(argv[class_arg], system_loader);
    if (main_class != NULL)
        // TODO 初始化一个主函数
        initClass(main_class);

    if (exceptionOccurred())
        // TODO 大概是处理异常
        goto error;

    // TODO 下面一整段
    mb = lookupMethod(main_class, SYMBOL(main),
                      SYMBOL(_array_java_lang_String__V));

    if (mb == NULL || !(mb->access_flags & ACC_STATIC)) {
        signalException(java_lang_NoSuchMethodError, "main");
        goto error;
    }

    /* Create the String array holding the command line args */

    i = class_arg + 1;
    if ((array_class = findArrayClass(SYMBOL(array_java_lang_String))) &&
        (array = allocArray(array_class, argc - i, sizeof(Object *)))) {
        Object **args = ARRAY_DATA(array, Object*) - i;

        for (; i < argc; i++)
            if (!(args[i] = Cstr2String(argv[i])))
                break;

        /* Call the main method */
        if (i == argc)
            executeStaticMethod(main_class, mb, array);
    }

    error:
    /* ExceptionOccurred returns the exception or NULL, which is OK
       for normal conditionals, but not here... */
    if ((status = exceptionOccurred() ? 1 : 0))
        uncaughtException();

    /* Wait for all but daemon threads to die */
    mainThreadWaitToExitVM();
    // TODO 关闭虚拟机
    exitVM(status);

    /* Keep the compiler happy */
    return 0;
}

上面简单地进行了注释,我们根据这个流程做分析,首先这一篇分析解析参数。


// 解析命令参数
    class_arg = parseCommandLine(argc, argv, &args);
这里传入的参数有三个,前两个是main函数的参数,代表了命令行的参数个数和参数数组,第三个是运行的初始化参数

typedef struct InitArgs {
    int asyncgc;
    int verbosegc;
    int verbosedll;
    int verboseclass;

    int compact_specified; /* Whether compaction has been given on the
                              command line, and the value if it has */
    int do_compact;

    int trace_jni_sigs;

    char *classpath; //classpath字面意思

    char *bootpath;
    char *bootpath_a;
    char *bootpath_p;
    char *bootpath_c;
    char *bootpath_v;

    int java_stack;
    unsigned long min_heap; // 最小堆栈值
    unsigned long max_heap; // 最大堆栈值

    Property *commandline_props;
    int props_count;

    void *main_stack_base; // 运行的类栈

    /* JNI invocation API hooks */
    
    int (*vfprintf)(FILE *stream, const char *fmt, va_list ap);
    void (*exit)(int status);
    void (*abort)(void);

#ifdef INLINING
    unsigned int codemem;
    int replication_threshold;
    int profile_threshold;
    int branch_patching_dup;
    int branch_patching;
    int print_codestats;
    int join_blocks;
    int profiling;
#endif

#ifdef HAVE_PROFILE_STUBS
    int dump_stubs_profiles;
#endif
} InitArgs;
这个是这个初始化参数的结构体,注释了解析命令行参数需要用的参数的含义


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值