Java虚拟机的启动与程序的执行

28、Java 异常处理与程序执行全解析 本文深入解析了Java的异常处理机制与程序执行过程。内容涵盖Java异常的分类(检查型与非检查型)、异常分析规则、处理机制以及最佳实践。此外,还详细介绍了Java虚拟机的启动过程、程序执行的各个阶段,以及异常处理对程序健壮性和性能的影响。通过示例代码和流程图,帮助读者更好地理解Java异常处理及程序运行原理。 阅读详情

这篇文章是从 OpenJDK 源码的角度讲当我们执行了

java -classpath . hello

之后,java.exe 怎样从 main 函数開始运行,启动虚拟机,并运行字节码中的代码。

实验环境

要了解一个系统是怎样执行的,光看是不行的,要实际地执行,调试,改动才干对系统的动作方式有所了解。

起初我是依照 GitHub 上的一个项目 OpenJDK-Research 在 windows 7 64位平台上,使用 Visual Studio 2010 来调试,执行的。可是后来发现,这个项目只编译了HotSpot虚拟机, java.exe 并没有编译。

这里我们首先弄明确 java.exe 和虚拟机之间的关系。我们使用 Visual Studio 编译出的 HotSpot 是虚拟机,是作为动态链接库的形式被 java.exe 载入的。java.exe 负责解析參数,载入虚拟机链接库,它须要调用虚拟机中的函数来完毕运行 Java 程序的功能。所以,你在HotSpot的源码中找不到启动的程序的 main 函数,本来在 openjdk7 中,虚拟机是带有一个启动器的,在文件夹 openjdk/hotspot/src/share/tools/launcher/java.c 中能够找到 main 函数,可是在 openjdk8 中,这个启动器不见了,被放在 openjdk/jdk 文件夹下,而不是 openjdk/hotspot 文件夹下了,给我们的学习过程造成了伤害。

所以我后来就在 linux 平台上调试了,由于在 windows 平台上,我始终没有把整个 openjdk8 编译成功,编译不出java.exe, 只编译了 hotspot,是看不到从 main 函数開始的运行的。关于怎样在 linux 平台下编译调试 openjdk8,能够參考我的还有一篇文章 在Ubuntu 12.04 上编译 openjdk8.

调用栈

jdk8u/jdk/src/share/bin/main.c::WinMain/main
  jdk8u/jdk/src/share/bin/java.c::JLI_Launch
    jdk8u/jdk/src/solaris/bin/java_md_solinux.c::LoadJavaVM # Load JVM Library: libjvm.so
    jdk8u/jdk/src/solaris/bin/java_md_solinux.c::JVMInit # Create JVM
      jdk8u/jdk/src/share/bin/java.c::ContinueInNewThread
        jdk8u/jdk/src/solaris/bin/java_md_solinux.c::ContinueInNewThread0(JavaMain, threadStackSize, (void*)&args);
          pthread_create(&tid, &attr, (void *(*)(void*))continuation, (void*)args)
            jdk8u/jdk/src/share/bin/java.c::JavaMain
              jdk8u/jdk/src/share/bin/java.c::InitializeJVM
                jdk8u\hotspot\src\share\vm\prims\jni.cpp::JNI_CreateJavaVM


运行过程

  • main.c (jdk8u/jdk/src/share/bin/main.c)
#ifdef JAVAW

char **__initenv;

int WINAPI
WinMain(HINSTANCE inst, HINSTANCE previnst, LPSTR cmdline, int cmdshow)
{
    int margc;
    char** margv;
    const jboolean const_javaw = JNI_TRUE;

    __initenv = _environ;
#else /* JAVAW */
int
main(int argc, char **argv)
{
    int margc;
    char** margv;
    const jboolean const_javaw = JNI_FALSE;
#endif /* JAVAW */
#ifdef _WIN32
    {
        int i = 0;
        if (getenv(JLDEBUG_ENV_ENTRY) != NULL) {
            printf("Windows original main args:\n");
            for (i = 0 ; i < __argc ; i++) {
                printf("wwwd_args[%d] = %s\n", i, __argv[i]);
            }
        }
    }
    JLI_CmdToArgs(GetCommandLine());
    margc = JLI_GetStdArgc();
    // add one more to mark the end
    margv = (char **)JLI_MemAlloc((margc + 1) * (sizeof(char *)));
    {
        int i = 0;
        StdArg *stdargs = JLI_GetStdArgs();
        for (i = 0 ; i < margc ; i++) {
            margv[i] = stdargs[i].arg;
        }
        margv[i] = NULL;
    }
#else /* *NIXES */
    margc = argc;
    margv = argv;
#endif /* WIN32 */
    return JLI_Launch(margc, margv,
                   sizeof(const_jargs) / sizeof(char *), const_jargs,
                   sizeof(const_appclasspath) / sizeof(char *), const_appclasspath,
                   FULL_VERSION,
                   DOT_VERSION,
                   (const_progname != NULL) ? const_progname : *margv,
                   (const_launcher != NULL) ? const_launcher : *margv,
                   (const_jargs != NULL) ? JNI_TRUE : JNI_FALSE,
                   const_cpwildcard, const_javaw, const_ergo_class);
}

这就是传说中的 main 函数的真身,能够看出,它针对操作系统是否使用 Windows ,运行了不同的代码段,终于调用JLI_Launch 函数。

  • JLI_Lanuch(jdk8u/jdk/src/share/bin/java.c)
int
JLI_Launch(int argc, char ** argv,              /* main argc, argc */
        int jargc, const char** jargv,          /* java args */
        int appclassc, const char** appclassv,  /* app classpath */
        const char* fullversion,                /* full version defined */
        const char* dotversion,                 /* dot version defined */
        const char* pname,                      /* program name */
        const char* lname,                      /* launcher name */
        jboolean javaargs,                      /* JAVA_ARGS */
        jboolean cpwildcard,                    /* classpath wildcard*/
        jboolean javaw,                         /* windows-only javaw */
        jint ergo                               /* ergonomics class policy */
)
{

...

    if (!LoadJavaVM(jvmpath, &ifn)) {
        return(6);
    }

...

    return JVMInit(&ifn, threadStackSize, argc, argv, mode, what, ret);

}

从这里能够看出 JLI_Lanuch 的各个參数的含义, 我列出了关键代码, 当中 LoadJavaVM 完毕加载虚拟机动态链接库,并初始化 ifn 中的函数指针,HotSpot虚拟机就是这样向启动器 java 提供功能。

  • LoadJavaVM (jdk8u/jdk/src/solaris/bin/java_md_solinux.c)

这个函数涉及动态链接库,不同操作系统有不同接口,这里是针对 linux 的。

jboolean
LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn)
{
    ...

    libjvm = dlopen(jvmpath, RTLD_NOW + RTLD_GLOBAL);

    ...

    ifn->CreateJavaVM = (CreateJavaVM_t)
    dlsym(libjvm, "JNI_CreateJavaVM");

    ifn->GetDefaultJavaVMInitArgs = (GetDefaultJavaVMInitArgs_t)
    dlsym(libjvm, "JNI_GetDefaultJavaVMInitArgs");

    ifn->GetCreatedJavaVMs = (GetCreatedJavaVMs_t)
        dlsym(libjvm, "JNI_GetCreatedJavaVMs");

  ...

从这里能够看出加载动态链接库以及初始化 ifn 数据结构的代码。在我的调试版本号中,javapath 指向之前编译出的动态链接库 jdk8u/build/fastdebug/jdk/lib/i386/server/libjvm.so.

  • JVM_Init(jdk8u/jdk/src/solaris/bin/java_md_solinux.c)

回到 JLI_Lanuch 函数,我们终于进入 JVM_Init, 这个函数会启动一个新线程。

int
JVMInit(InvocationFunctions* ifn, jlong threadStackSize,
        int argc, char **argv,
        int mode, char *what, int ret)
{
    ShowSplashScreen();
    return ContinueInNewThread(ifn, threadStackSize, argc, argv, mode, what, ret);
}

ContinueInNewThread 会调用还有一个函数 ContinueInNewThread0 启动线程,运行 JavaMain 函数:

int
ContinueInNewThread0(int (JNICALL *continuation)(void *), jlong stack_size, void * args) {

...

    if (pthread_create(&tid, &attr, (void *(*)(void*))continuation, (void*)args) == 0) {
      void * tmp;
      pthread_join(tid, &tmp);
      rslt = (int)tmp;
    } else {
     /*
      * Continue execution in current thread if for some reason (e.g. out of
      * memory/LWP)  a new thread can't be created. This will likely fail
      * later in continuation as JNI_CreateJavaVM needs to create quite a
      * few new threads, anyway, just give it a try..
      */
      rslt = continuation(args);
    }

...


  • JavaMain(jdk8u/jdk/src/share/bin/java.c)

这个函数会初始化虚拟机,载入各种类,并运行应用程序中的 main 函数。凝视非常具体。

int JNICALL
JavaMain(void * _args)
{
    JavaMainArgs *args = (JavaMainArgs *)_args;
    int argc = args->argc;
    char **argv = args->argv;
    int mode = args->mode;
    char *what = args->what;
    InvocationFunctions ifn = args->ifn;

    JavaVM *vm = 0;
    JNIEnv *env = 0;
    jclass mainClass = NULL;
    jclass appClass = NULL; // actual application class being launched
    jmethodID mainID;
    jobjectArray mainArgs;
    int ret = 0;
    jlong start, end;

    RegisterThread();

    /* Initialize the virtual machine */
    start = CounterGet();
    if (!InitializeJVM(&vm, &env, &ifn)) {
        JLI_ReportErrorMessage(JVM_ERROR1);
        exit(1);
    }

    ...

    ret = 1;

    /*
     * Get the application's main class.
     *
     * See bugid 5030265.  The Main-Class name has already been parsed
     * from the manifest, but not parsed properly for UTF-8 support.
     * Hence the code here ignores the value previously extracted and
     * uses the pre-existing code to reextract the value.  This is
     * possibly an end of release cycle expedient.  However, it has
     * also been discovered that passing some character sets through
     * the environment has "strange" behavior on some variants of
     * Windows.  Hence, maybe the manifest parsing code local to the
     * launcher should never be enhanced.
     *
     * Hence, future work should either:
     *     1)   Correct the local parsing code and verify that the
     *          Main-Class attribute gets properly passed through
     *          all environments,
     *     2)   Remove the vestages of maintaining main_class through
     *          the environment (and remove these comments).
     *
     * This method also correctly handles launching existing JavaFX
     * applications that may or may not have a Main-Class manifest entry.
     */
    mainClass = LoadMainClass(env, mode, what);
    CHECK_EXCEPTION_NULL_LEAVE(mainClass);
    /*
     * In some cases when launching an application that needs a helper, e.g., a
     * JavaFX application with no main method, the mainClass will not be the
     * applications own main class but rather a helper class. To keep things
     * consistent in the UI we need to track and report the application main class.
     */
    appClass = GetApplicationClass(env);
    NULL_CHECK_RETURN_VALUE(appClass, -1);
    /*
     * PostJVMInit uses the class name as the application name for GUI purposes,
     * for example, on OSX this sets the application name in the menu bar for
     * both SWT and JavaFX. So we'll pass the actual application class here
     * instead of mainClass as that may be a launcher or helper class instead
     * of the application class.
     */
    PostJVMInit(env, appClass, vm);
    /*
     * The LoadMainClass not only loads the main class, it will also ensure
     * that the main method's signature is correct, therefore further checking
     * is not required. The main method is invoked here so that extraneous java
     * stacks are not in the application stack trace.
     */
    mainID = (*env)->GetStaticMethodID(env, mainClass, "main",
                                       "([Ljava/lang/String;)V");
    CHECK_EXCEPTION_NULL_LEAVE(mainID);

    /* Build platform specific argument array */
    mainArgs = CreateApplicationArgs(env, argv, argc);
    CHECK_EXCEPTION_NULL_LEAVE(mainArgs);

    /* Invoke main method. */
    (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);

    /*
     * The launcher's exit code (in the absence of calls to
     * System.exit) will be non-zero if main threw an exception.
     */
    ret = (*env)->ExceptionOccurred(env) == NULL ? 0 : 1;
    LEAVE();
}

注意 InitializeJVM 函数,它会调用之前初始化的 ifn 数据结构中的 CreateJavaVM 函数.

  • InitializeJVM(jdk8u/jdk/src/share/bin/java.c::InitializeJVM)
static jboolean
InitializeJVM(JavaVM **pvm, JNIEnv **penv, InvocationFunctions *ifn)
{
    JavaVMInitArgs args;
    jint r;

    memset(&args, 0, sizeof(args));
    args.version  = JNI_VERSION_1_2;
    args.nOptions = numOptions;
    args.options  = options;
    args.ignoreUnrecognized = JNI_FALSE;

    if (JLI_IsTraceLauncher()) {
        int i = 0;
        printf("JavaVM args:\n    ");
        printf("version 0x%08lx, ", (long)args.version);
        printf("ignoreUnrecognized is %s, ",
               args.ignoreUnrecognized ? "JNI_TRUE" : "JNI_FALSE");
        printf("nOptions is %ld\n", (long)args.nOptions);
        for (i = 0; i < numOptions; i++)
            printf("    option[%2d] = '%s'\n",
                   i, args.options[i].optionString);
    }

    r = ifn->CreateJavaVM(pvm, (void **)penv, &args);
    JLI_MemFree(options);
    return r == JNI_OK;
}

ifn->CreateJavaVM指向虚拟机动态链接库中的 JNI_CreateJavaVM 函数,这个函数会真正创建虚拟机。 这个函数运行后,pvm, penv 的值就会被设定,我们能够比較下运行前后它们的值,来看看它们的作用。

// before r = ifn->CreateJavaVM(pvm, (void **)penv, &args);

(gdb) p *pvm
$8 = (JavaVM *) 0x0
(gdb) p *penv
$9 = (JNIEnv *) 0x0

// after r = ifn->CreateJavaVM(pvm, (void **)penv, &args);

(gdb) p ***penv
$14 = {reserved0 = 0x0, reserved1 = 0x0, reserved2 = 0x0, reserved3 = 0x0, 
  GetVersion = 0xb6ede599 <jni_GetVersion>, 
  DefineClass = 0xb6eb20a0 <jni_DefineClass>, 
  FindClass = 0xb6eb253c <jni_FindClass>, 
  FromReflectedMethod = 0xb6eb2b17 <jni_FromReflectedMethod>, 
  FromReflectedField = 0xb6eb2edb <jni_FromReflectedField>, 
  ...
  ...
  }

(gdb) p ***pvm
$15 = {reserved0 = 0x0, reserved1 = 0x0, reserved2 = 0x0, 
  DestroyJavaVM = 0xb6edf1e8 <jni_DestroyJavaVM>, 
  AttachCurrentThread = 0xb6edf69a <jni_AttachCurrentThread>, 
  DetachCurrentThread = 0xb6edf795 <jni_DetachCurrentThread>, 
  GetEnv = 0xb6edf8d3 <jni_GetEnv>, 
  AttachCurrentThreadAsDaemon = 0xb6edfa7d <jni_AttachCurrentThreadAsDaemon>}

能够看出它们得到了hotspot 中以 jni_ 开头的一些函数,虚拟机正是以这种方式向外提供功能。我们大概看一下JNI_CreateJavaVM 的功能。


    • JNI_CreateJavaVM(jdk8u\hotspot\src\share\vm\prims\jni.cpp)
    _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_CreateJavaVM(JavaVM **vm, void **penv, void *args) {
      ...
    
        result = Threads::create_vm((JavaVMInitArgs*) args, &can_try_again);
      if (result == JNI_OK) {
        JavaThread *thread = JavaThread::current();
        /* thread is thread_in_vm here */
        *vm = (JavaVM *)(&main_vm);
        *(JNIEnv**)penv = thread->jni_environment();
    
        // Tracks the time application was running before GC
        RuntimeService::record_application_start();
    
        // Notify JVMTI
        if (JvmtiExport::should_post_thread_life()) {
           JvmtiExport::post_thread_start(thread);
        }
    
        ...
    
      }
    
      ...
    
    }
    

    当中的 create_vm 函数是虚拟机初始化的关键,它初始化了虚拟机的大部分组件。另外能够看到 vm, penv 的值被设定。

    这个函数位于 jdk8u\hotspot\src\share\vm\prims\jni.cpp。

    我之前在 Windows 下调试,直接调试的 HotSpot 动态链接库,能够看到的第一个函数就是 JNI_CreateJavaVM, 之前的调用都位于 java.exe 代码中。由于 Windows 中 java.exe 不是我们自己编译的,看不到当中调用关系。例如以下图所看到的:


    同一时候能够看到两个线程

    解放双手:用KUKA示教器白键一键触发复杂工艺,自定义你的快捷指令 本文详细介绍了如何利用KUKA示教器的工艺白键功能,通过自定义快捷指令一键触发复杂工艺,显著提升自动化产线效率。文章涵盖UserTech技术栈解析、KRL脚本封装、人机交互视觉工程及工业实战策略,帮助工程师实现机械臂操作的高阶优化。 阅读详情

    相关推荐

    内存管理(二)——内存分段

    内存分段

    weixin_43844995的博客 2693

    java程序执行流程、与虚拟机的关系

    注意:此文章属于自己的整理笔记,如果哪里有错误希望大家指出来,我会及时修改。下文是在正确的安装了JDK的基础上才有的。dos命令:javac 空格 *.java      //通过java编译器来编辑java源文件(*.java)。编译成功后后在同级目录下生成 *.class文件(也叫字节码文件、bytecode)。 该class文件名与*.java源文件中定义的类名相同,如果*.java源文件中的类使用public关键字修饰,那么这个类名必须与*.java这个源文件的文件名相同!一个java源文件中只能有

    CrazyBadHat的专栏 507

    WS2812呼吸灯效果实战:用STM32的PWM+DMA实现流畅渐变(附完整代码)

    本文详细介绍了如何使用STM32的PWM+DMA技术实现WS2812呼吸灯效果,提供完整的代码示例和调试技巧。通过PWM波形编码和DMA传输机制,解决了传统IO模拟控制方式的高CPU占用问题,实现了流畅的LED渐变效果,适用于各种嵌入式开发场景。

    weixin_30566063的博客 452

    JVM工作原理

    JVM工作原理和特点主要是指操作系统装入JVM是通过jdk中Java.exe来完成,通过下面4步来完成JVM环境. 1.创建JVM装载环境和配置 2.装载JVM.dll 3.初始化JVM.dll并挂界到JNIENV(JNI调用接口)实例 4.调用JNIEnv实例装载并处理class类。   一.JVM装入环境,JVM提供的方式是操作系统的动态连接文件.既然是文件那就一个装入路

    tkwo123的专栏 801

    深度学习之基于Pytorch手指静脉识别系统(

    一、项目背景与目标手指静脉识别技术是一种新兴的生物特征识别技术,它依据人类手指中流动的血液可吸收特定波长的光线这一科学原理,利用手指内的静脉分布图像来进行身份识别。与传统的生物识别技术(如指纹识别)相比,手指静脉识别技术具有不易伪造、识别精度高、非接触性等特点,因此在安全性要求较高的场景(如金融、医疗、公安等)具有广阔的应用前景。本项目旨在利用PyTorch深度学习框架,构建一套高效、准确的手指静脉识别系统。

    Q1744828575的博客 831

    IQA图像质量评价 数据集介绍(LIVE、TID2013、CSIQ、LIVEC、KonIQ-10K)

    LIVE、TID2013、CSIQ、LIVEC、KonIQ-10K 数据集介绍

    qq_37925923的博客 1万+

    Java虚拟机的启动与程序的运行

    这篇文章是从 OpenJDK 源代码的角度讲当我们运行了 java -classpath . hello 之后,java.exe 如何从 main 函数开始执行,启动虚拟机,并执行字节码中的代码。 实验环境 要了解一个系统是如何运行的,光看是不行的,要实际地运行,调试,修改才能对系统的动作方式有所了解。 起初我是按照 GitHub 上的一个项目O...

    603

    VSCode下载、安装+C语言环境配置(超详细)

    ps:我的更改部分:"D:/BaiduNetdiskDownload/x86_64-8.1.0-release-win32-seh-rt_v6-rev0/mingw64。③ 找到【系统变量】中的【Path】变量 ---- 双击打开后,将刚刚复制的地址添加进去 ---- 点击【确定】;① 双击【此电脑】---- 点击【属性】---- 进入到下面这个界面,单击【高级系统设置】;② 进入到 系统属性界面 ---- 点击【环境变量】,进入环境变量页面;并进行安装,安装成功后,打开VSCode;

    weixin_48820458的博客 1万+

    Java虚拟机启动整体流程和基础学习(内容很多,不可快餐阅读),推理+源码论证

    请花点时间具体看看Java虚拟机的启动吧,其他搜到的资料,请使用源码论证一下,谢谢

    XuJiaKai的博客 2390

    AD7768与STM32F439的硬件设计避坑指南:如何优化高精度ADC系统的电源与PCB布局

    本文详细解析了AD7768与STM32F439在高精度ADC系统硬件设计中的关键问题与优化方案。从电源系统设计、PCB布局到基准电压选型,提供了实用的避坑指南和实测数据,帮助工程师提升系统性能至110dB动态范围。特别强调了SPI信号布线和电源滤波对ADC精度的重要影响。

    sugar的博客 735

    深度解析大众点评反爬机制:构建高可用店铺评论采集系统(2026最新实战)

    在中文互联网数据采集领域,大众点评(现归属美团)始终占据着特殊地位。其丰富的UGC(用户生成内容)包含了超过2亿条真实店铺评论、数百万家商户的详细POI信息以及用户行为数据,对商业分析、口碑监测、本地生活趋势研究具有不可替代的价值。然而,大众点评的安全团队投入了顶级资源构建反爬系统——从请求签名、行为验证到设备指纹,其防御强度甚至超过多数电商平台。本文将完整呈现一套2026年依然有效的技术方案,包括破解核心参数_token、动态代理池维护、无头浏览器指纹伪装等,最终产出一个生产级采集框架。目录。

    2201_76125261的博客 811

    Java程序main方法执行流程

    Java程序main方法执行流程 当我们编写完java源代码程序后,经过javac编译后,执行java命令执行这个程序时,是怎么一步步的调用到我们程序中的main方法的呢?今天通过查看OpenJdk的源码来揭开它的神秘面纱。 java命令是在安装jre/jdk时...

    m0_37695902的博客 2584

    数仓解惑:数据仓库常见建模方法与大数据领域建模实例综述

    为什么需要数据建模? 为什么要进行数据仓库建模? 随着DT时代互联网、智能设备等信息技术的发展,数据开始井喷式的增长,如何讲这些数据进行有序、有结构地分类组织存储是我们面临的一个挑战。 如果把数据看作图书馆里的书,我们希望看到它们在书架上分门别类地放置,而不是乱糟糟的 大数据的数仓建模是通过建模的方法更好的组织、存储数据,以便在 性能、成本、效率和数据质量之间找到最佳平衡点。一般主要从下面四点考虑 ...

    云祁QI 5849

    Java虚拟机详解

    概念     虚拟机是一种抽象化的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实现的。Java虚拟机有自己完善的硬体架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。JVM屏蔽了与具体操作系统平台相关的信息,使得Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。 运行过程 一个运行时的Java虚拟机实例的天职是:负责

    帅性而为1号的博客 1703

    visio安装包

    Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

    VC中sqlite的使用

    在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

    Java虚拟机调用jni_JNI攻略之十一――启动虚拟机调用java类

    JNI攻略之十一――启动虚拟机调用java类江苏无锡缪小东一、一个简单的java程序下面是一个简单的java程序!主要是供虚拟机直接调用的!我们可以编写任意的java程序,然后在c中调用虚拟机执行它!通常我们会有此场景:某些本地系统可能不支持多线程,但你对java的多线程又比较精通,同时对c还是比较了解,此时我们就可以在c中调用虚拟机,执行改线程程序!更一般的:以前有一个用c写的服务器程序,它可以...

    weixin_28788777的博客 334

    jre9下载 jdk9

    (Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

    Java的运行 线程

    我们编写出来的java文件叫做源文件,内部的代码也叫源代码,是我们人能看懂的代码,通过javac指令将它编译为后缀名为class的二进制代码,这两步都是在磁盘中进行的。随后文件再通过java指令被加载到内存中,再给到CPU中进行运行。所有正在运行的软件都在内存中有自己的内存空间,其中就包括JVM。JVM又叫做Java虚拟机,专门用来运行Java程序,java的数据给到JVM,在JVM内部也分为很多的内存空间,包括:方法区、堆、虚拟机栈。JVM相关的后续课程再作教学。

    a1463073169的博客 643

    SAP B1中文培訓教材_SDK

    公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

    java虚拟机之JVM生命周期

    java生命周期分为以下三部分:启动,运行,消亡。 启动。启动一个Java程序时,一个JVM实例就产生了,任何一个拥有public static void main(String[] args)函数的class都可以作为JVM实例运行的起点。 运行。main()作为该程序初始线程的起点,任何其他线程均由该线程启动。 消亡。当程序中的所有非守护线程都终止时,JVM才退出;若安...

    Yan18200289607的专栏 201

    JNI攻略之十一――启动虚拟机调用java类

    JNI攻略之十一――启动虚拟机调用java类<br /> 一、      一个简单的java程序<br />       下面是一个简单的java程序!主要是供虚拟机直接调用的!我们可以编写任意的java程序,然后在c中调用虚拟机执行它!通常我们会有此场景:某些本地系统可能不支持多线程,但你对java的多线程又比较精通,同时对c还是比较了解,此时我们就可以在c中调用虚拟机,执行改线程程序!更一般的:以前有一个用c写的服务器程序,它可以介绍客户的申请,当然这种申请在某一个时刻肯定是很多很多的,因此我们就想让这

    389

    深入Java虚拟机笔记(五):剖析HotSpot的Launcher

    虽然HotSpot只是OpenJDK项目的一个功能子集,但在其中占据非常重要的地位 HotSpot目录下四大子目录: agent:包含Serviceability Agent的客户端的实现 make:用于build出HotSpot的各种配置文件 src:包括HotSpot的所有源码 test:单元测试 Launcher是一直用于启动JVM进程的启动器,有两种,一种windows平台下运

    w 2542

    Java程序员从笨鸟到菜鸟之(九十二)深入java虚拟机(一)——java虚拟机底层结构详解

    Java虚拟机 Java虚拟机(Java Virtual Machine) 简称JVM Java虚拟机是一个想象中的机器,在实际的计算机上通过软件模拟来实现。Java虚拟机有自己想象中的硬件,如处理器、堆栈、寄存器等,还具有相应的指令系统。下面我们就来看一下这几部分比较重要的java虚拟机的结构 JVM寄存器 所有的CPU均包含用于保存系统状态和处理器所需信息的寄存器组。如果虚拟

    bamboo_cqh的博客 400

    虚拟机启动只有下划线_跟着我来对Java虚拟机快速认识下吧!

    java虚拟机(Java Virtual Machine 简称JVM)是一个可以执行java字节码的(.class)进程。作为一个Java程序员,我们每天都在写Java代码,我们写的代码都是在一个叫做Java虚拟机的东西上执行的。但是如果要问什么是虚拟机,恐怕很多人就会模棱两可了。在本文中,我会写下我对虚拟机的理解。因为能力所限,可能有些地方描述的不够欠当。如果你有不同的理解,欢迎下方评论区交流或...

    weixin_39564036的博客 357

    java vm_快速认识Java虚拟机

    Java虚拟机也是一个可运行的程序,它或者全部用软件方式来实现,或者采用硬件或软件结合的方式来实现。当启动一个Java程序时,就会运行一个Java虚拟机,每个Java程序都会对应一个Java虚拟机,运行中的Java虚拟机,也可以称为Java虚拟机的一个实例。Java程序运行结束关闭后,运行这个程序的Java虚拟机也会关闭。例如,如果在电脑运行了三个Java程序,就会有三个Java虚拟机在运行。ja...

    weixin_42486094的博客 514
    上一篇: win7 中 Alt+Ctrl+方向键电脑屏幕选择问题
    下一篇: JVM-系统初始化
    DViewer
    博客等级 码龄16年 16粉丝 6原创
    评论
    成就一亿技术人!
    拼手气红包6.0元
    还能输入1000个字符
     
     条评论被折叠 查看
    添加红包

    请填写红包祝福语或标题

    个

    红包个数最小为10个

    元

    红包金额最低5元

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

    抵扣说明:

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

    余额充值