为什么Java程序需要运行在虚拟机上

因为Java在设计之初的跨平台特性,我们知道Java程序是运行在Java虚拟机上的。如果你要问为什么Java程序要运行在虚拟机上,我可以反问你几个问题。

为什么买来的电器插上电就能直接使用?你可能会说,因为电是基础设施。电源有统一的标准,电器有统一的标准,所以买来的电器插上电就能用。

不同的电器需要的电源标准不同(台灯和电饭煲的功率),为什么我们不能给不同的电器配置不同的电源呢?因为太麻烦了,虽然这样我们能让每个电器都达到最适应的效率,但是代价未免太大了些。想一想,别人需要用你家的电器时首先要先配一个合适的发电机。

所以电力基础设施需要把不同的发电方式发出的电接入同一个电网, 电力公司负责调度分配电力,并且在使用的时候提供相同标准的输出。虽然这个过程损失了一部分电力,但是大大提高了我们使用电器的便利。

那么回过头来看Java虚拟机。为什么Java程序要运行在虚拟机上,这是因为我们需要实现一次编译到处运行(统一的电源标准)。那么为什么C++不是跨平台的呢,因为C++编译时会转换为与机器关联的机器码,这导致了C++编译的程序只能在特定的机器上运行(依赖发电机)

Java的内存区域

说回Java虚拟机,我们知道C++程序员是需要手动清理内存的,Java程序不需要手动清理,其内存管理由虚拟机负责。那么Java是如何管理内存的呢?

Java虚拟机会把它管理的内存划分成几个不同的数据区。如下图所示:

1.程序计数器(PC寄存器)

程序计数器时当前线程所执行的字节码的行号指示器。因为Java虚拟机的多线程轮换是通过线程轮流切换分配处理器执行时间来实现的,所以每个线程都会有一个程序计数器。

另外,Java程序既有Java方法也有本地方法。假如线程执行的是Java方法,那么程序计数器记录的是当前执行的字节码指令的地址。如果是本地方法,则计数器值为空。此区域是Java虚拟机规范中唯一的没有规定OutOfMemoryError的区域。

2.Java虚拟机栈

Java虚拟机栈也是线程私有的,它的生命周期与线程相同。虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链表、方法出口等信息。当退出当前执行的方法时,不管是正常返回还是异常返回,Java虚拟机均会弹出当前线程栈帧并舍弃。

3.本地方法栈

本地方法栈跟Java虚拟机栈的作用基本相同,本地方法栈其实是Native方法执行过程中存储方法的数据结构的栈空间。

4.Java堆

Java堆(Java Heap)是Java虚拟机管理内存中最大的一块。Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的时存放对象实例。另外Java堆也是垃圾回收器管理的主要区域,因此很多时候也成为「GC堆」。

5.方法区

方法区和Java堆一样,是各个线程共享的内存区域,它是用来存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

其中常量会单独放置在运行时常量池(JDK8中放到了堆中)中。运行时常量池具备动态性,也就是在程序运行期间也可以将新的常量放入池中,这种特性使用较多的事String类的intern()方法。

6.直接内存

直接内存不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域。但是这部分内存的频繁使用也可能导致OutOfMemoryError异常出现。

JDK 1.4中新加入了NIO(New Input/Output)类,引入了一种基于通道与缓冲区的I/O方式,它可以使用本地函数库直接分配堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。在一些常见中这种操作能显著提高性能。

总结

本篇我们了解了为什么Java虚拟机需要运行在虚拟机上,用了一个电源和电器的例子。Java虚拟机将内存分成两种,线程共享和线程独占内存区域。其中线程独占的区域有程序计数器、Java虚拟机栈、本地方法栈。线程共享区域有Java堆、方法区(包括运行时常量池)。在Java虚拟机运行时数据区之外还有直接内存,此区域可以使用堆外内存来提升I/O的速度。

JVM学习笔记(一):Java虚拟机和虚拟机内存区域的更多相关文章

  1. JVM学习笔记:Java运行时数据区域

    JVM执行Java程序的过程中,会使用到各种数据区域,这些区域有各自的用途.创建和销毁时间.根据<Java虚拟机规范>,JVM包括下列几个运行时数据区域,如下图所示: 其中红色部分是线程私 ...

  2. JVM学习笔记(1)--运行时数据区域

    运行时数据区域 相对于c,c++.程序设计时,java并不需要手动释放或者创建内存用于存放程序,这的确使得java开发变得容易和轻松,一旦有一天出现了内存泄漏或者内存溢出的问题,如果不了解JVM虚拟机 ...

  3. 【JVM学习笔记二】垃圾收集器与内存分配策略

    1. 概述 1) GC的历史比Java久远 2) GC需要完成的三件事: | 哪些内存需要回收 | 什么时候回收 | 如何回收 3) Java内存运行时区域各个部分: | Java虚拟机栈.计数器.本 ...

  4. JVM学习笔记三:垃圾收集器与内存分配策略

    内存回收与分配重点关注的是堆内存和方法区内存(程序计数器占用小,虚拟机栈和本地方法栈随线程有相同的生命周期). 一.判断对象是否存活? 1. 引用计数算法 优势:实现简单,效率高. 致命缺陷:无法解决 ...

  5. JVM学习笔记三:垃圾收集器及内存管理策略

    垃圾收集器 上文说到了垃圾收集算法,这次我们聊一下HotSpot的具体垃圾收集器的实现,以JDK1.7为例,其包含的可选垃圾收集器如下图: 不同收集器之间的连线,代表它们可以搭配使用,收集器所属的区域 ...

  6. 【Java虚拟机】JVM学习笔记之GC

    JVM学习笔记二之GC GC即垃圾回收,在C++中垃圾回收由程序员自己来做,例如可以用free和delete来回收对象.而在Java中,JVM替程序员来执行垃圾回收的工作,下面看看GC的详细原理和执行 ...

  7. JVM学习笔记:虚拟机的类加载机制

    JVM类加载机制分两部分来总结: (1)类加载过程 (2)类加载器 一.JVM类加载过程 类的加载过程:加载 →连接(验证 → 准备 → 解析)→ 初始化. 类的生命周期:加载 →连接(验证 → 准备 ...

  8. JVM学习笔记-第七章-虚拟机类加载机制

    JVM学习笔记-第七章-虚拟机类加载机制 7.1 概述 Java虚拟机描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这个过程被 ...

  9. ☕【JVM技术指南】「JVM总结笔记」Java虚拟机垃圾回收认知和调优的"思南(司南)"【下部】

    承接上文 (完结撒花1-52系列)[JVM技术指南]「JVM总结笔记」Java虚拟机垃圾回收认知和调优的"思南(司南)"[上部] 并行收集器 并行收集器(也称为吞吐量收集器)是类似 ...

随机推荐

  1. PackageUtils

    import android.content.Context; import android.content.Intent; import android.content.pm.Application ...

  2. rally使用tempest进行测试

    安装 通过Rally进行Tempest测试,执行如下命令创建tempest实例,Rally会自动同步tempest代码至本地: rally verify create-verifier --name ...

  3. memcached-slab内存管理

    一.Memcache内存分配机制 关于这个机制网上有很多解释的,我个人的总结如下. Page为内存分配的最小单位. Memcached 的内存分配以page为单位,默认情况下一个page是1M,可以通 ...

  4. linux下正确卸载rpm包

    linux下正确卸载rpm包 rpm -qa | grep -i ntp 执行结果: [root@bogon elasticsearch-head]# rpm -qa | grep -i ntp fo ...

  5. nginx反向代理cookie相关

    http://blog.csdn.net/xiansky2015/article/details/51674997 http://www.jianshu.com/p/aeed2a56a3eb

  6. 7. grep

    grep命令 grep grep是通用正则表达式分析程序(General Regular Expression Parser)的缩写. grep命令可以在它的输入中搜索指定的字符串模式(Pattern ...

  7. Jenkins - Tips

    01 - RPM包安装方式 默认路径 配置文件:/etc/sysconfig/jenkins 日志文件:/var/log/jenkins/jenkins.log 执行文件:/usr/lib/jenki ...

  8. python装饰器的构建

    #!/usr/bin/python3# -*-coding:utf-8 -*-# @Time : 2019/9/27 17:04# @Author : v_ctaozhang import funct ...

  9. 【VS开发】【编程开发】【C/C++开发】结构体中的数组与指针的内存分配情况说明

    [VS开发][编程开发][C/C++开发]结构体中的数组与指针的内存分配情况说明 标签:[VS开发] [编程开发] 主要是疑惑在结构体定义的数组的内存空间与指针动态分配的内存空间,在地址上连续性.以及 ...

  10. Mac 每次重启终端后配置的不生效.需要重新source

    Mac 每次都要执行source ~/.bash_profile 配置的环境变量才生效 自己在 ~/.bash_profile 中配置环境变量, 可是每次重启终端后配置的不生效.需要重新执行 : $s ...