为什么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. NLP之电影评分数据的情感分析

    1.基于词袋模型的逻辑回归情感分类 # coding: utf-8 import re import numpy as np import pandas as pd from bs4 import B ...

  2. [spring]@Resource和@Autowired区别对比

    @Resource和@Autowired都是做bean的注入时使用,其实@Resource并不是Spring的注解,它的包是javax.annotation.Resource,需要导入,但是Sprin ...

  3. Selenium 2自动化测试实战35(HTML测试报告)

    HTML测试报告 显然,一份漂亮的测试报告展示自动化测试成果只有一个简单的log文件是不够的.HTMLTestRunner是python标准库unittest单元测试框架的一个扩展,它生成易于使用的H ...

  4. Hibernate 的一些注解配置

    网上参考资料很多,但总是不符合自身习惯,遂记录下来. 一对多的关系 如class与student的关系 class中 @OneToMany(mappedBy = "class") ...

  5. 一百一十七:CMS系统之注册页面对接短信验证码

    from flask import Blueprint, requestfrom exts import alidayufrom utils import restfulfrom utils.capt ...

  6. 开题报告中如何将一段文字插入到word表格中

    1,举例如下,打开空白word,设计一个20列的表格.任意一段文字. 2,选中这段文字,点击替换按钮.查找内容为“?”,替换为“^&,”(后面是逗号),并勾选“使用通配符”. 3,全部替换得到 ...

  7. .Netcore 2.0 Ocelot Api网关教程(3)- 路由聚合

    在实际的应用当中,经常会遇到同一个操作要请求多个api来执行.这里先假设一个应用场景:通过姓名获取一个人的个人信息(性别.年龄),而获取每种个人信息都要调用不同的api,难道要依次调用吗?在Ocelo ...

  8. DP,数论————洛谷P4317 花神的数论题(求1~n二进制中1的个数和)

    玄学代码(是洛谷题解里的一位dalao小粉兔写的) //数位DP(二进制)计算出f[i]为恰好有i个的方案数. //答案为∏(i^f[i]),快速幂解决. #include<bits/stdc+ ...

  9. PHP SQL注入

    开发者容易遗漏的输入点: HTTP头 X-Forwarded-For   获取用户ip User-Agent            获取浏览器 Referer                  获取之 ...

  10. USACO 1.2 Broken Necklace

    断点是白色的情况在做题的时候完全没有想到呢... 看到了数据才发现这个问题$qwq$ /* ID:Starry21 LANG:C++ TASK:beads */ #include<iostrea ...