为什么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. 数据库sequence的作用和用法

    转: 数据库sequence的作用和用法 2016年10月14日 19:51:03 很菜很菜的鸟 阅读数 14456 标签: oracle数据库db2sequence   seqence的作用: se ...

  2. 小D课堂 - 新版本微服务springcloud+Docker教程_5-08 断路器监控仪表参数

    笔记 8.断路器监控仪表参数讲解和模拟熔断     简介:讲解 断路器监控仪表盘参数和模拟熔断 1.sse  server-send-event推送到前端 资料:https://github.com/ ...

  3. 关于java面试题

    java的优点: Java是一种跨平台,适合于分布式计算环境的面向对象编程语言. 具体来说,它具有如下特性: 简单性.面向对象.分布式.解释型.可靠.安全.平台无关.可移植.高性能.多线程.动态性等.

  4. EM算法:入门案例

    概率分布 4种实验结果 \(E_1\) \(E_2\) \(E_3\) \(E_4\) 记录它们发生的次数 \(y_1\) \(y_2\) \(y_3\) \(y_4\) 记录次数结果 125 18 ...

  5. Swift3.0封装 AFN 的 GET&POST网络请求

    // // PSNetWorkManage.swift // WeiBoSwift // // Created by 思 彭 on 16/9/25. // Copyright © 2016年 思 彭. ...

  6. JavaWeb—Nginx介绍(转载)

    Nginx的产生 没有听过Nginx?那么一定听过它的"同行"Apache吧!Nginx同Apache一样都是一种WEB服务器.基于REST架构风格,以统一资源描述符(Unifor ...

  7. Python multiprocess模块(下)

    主要内容:(参考资料) 一. 管道 二. 数据共享 数据共享是不安全的 三. 进程池 进程池的map传参 进程池的同步方法 进程池的异步方法 详解apply和apply_async apply_asy ...

  8. LCA cogs 2450 2048 1588

    t1 2450距离 链接:http://cogs.pro:8081/cogs/problem/problem.php?pid=vSNNNVqga [题目描述] 在一个村子里有N个房子,一些双向的路连接 ...

  9. 【C/C++开发】try-cache-finnally捕获异常

    在c++中,可以直接抛出异常之后自己进行捕捉处理,如:(这样就可以在任何自己得到不想要的结果的时候进行中断,比如在进行数据库事务操作的时候,如果某一个语句返回SQL_ERROR则直接抛出异常,在cat ...

  10. 通过火狐谋智查询API

    谋智中文版网址 https://developer.mozilla.org 示例 site: developer.mozilla.org window 通过百度高级用法查API site: 网址 搜索 ...