java虚拟机被称为“虚拟”,因为它是一个抽象的计算机定义的规范。要运行一个Java程序,需要一个抽象的规范的具体实现。以下内容主要还是参考《Inside JVM》

什么是JVM?

JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。JVM三种不一样的地方:抽象的规范,一个具体的实现,运行时的实例。

JVM的生命周期

java虚拟机种运行的一个实例有着明确的“使命”:运行一个java程序,当程序启动时,产生一个运行实例,当程序运行完成时,实例就没了。如果同时启动三个java程序,在同一台电脑上,使用相同的实现方法,你就会得到三个java虚拟机的实例,每个java程序运行在自己的虚拟机实例上面。

Java虚拟机实例通过调用一些初始类的main()方法来开始运行其单独应用程序,该main()方法必须时公共(public),静态(static),无返回值的(void),并且接受一个字符串数组的参数(String[] args),按照上面定义的main()方法,任何一个类的main方法都可以作为程序启动的起点。


public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

在java虚拟机中,线程分两种:守护线程(daemon,也可以成为后台线程)和 非守护线程(non-daemon,前台线程)。


daemon守护线程是JVM自己用的,就比如我们常说的垃圾回收。non-daemon非守护线程,应用程序启动了main(),然后再调用我们自己写的方法。 一个java程序在运行时,只要非守护线程一直运行,那么java虚拟机实例就一直存在,当所有的java非守护线程中断时,java虚拟机实例也就消失了。当然我们也可以直接通过类Runtime或者类System调用exit()方法来使程序中断。

JVM的体系结构

在java虚拟机规范中,java虚拟机的行为是由子系统,内存区域,数据类型和指令来描述的。这些组件的目的与其说是决定内部架构的实现,更提供了一种严格定义的外部行为的实现。规范定义了所需的任何Java虚拟机的行为来实现这些抽象组件及其之间的交互。

一个Java虚拟机,包括主要的子系统和内存区域中描述的规范如前一章中提到,每个Java虚拟机有一个类装入器子系统:加载机制类型(类和接口)指定完全限定的名称。每个Java虚拟机还提供一个执行引擎:一种机制负责执行的指令包含在加载的类的方法。

当一个Java虚拟机运行一个程序的时候,他需要内存存储更多的东西,包括直接码和其它信息摘录加载类文件,程序实例化对象,参数方法,返回值,局部变量,计算的中间结果。虽然相同的数据区域运行在每一个java虚拟机的实现上,规范是抽象的,但具体运行这些数据区域的细节的时候还是需要(设计者)实现者来具体实现。

不同的java虚拟机的实现有很多不同的内存限制,有些实现需要很多的内存为其工作,而有的实现却需要的很少;有的实现可以利用java虚拟内存,有的却不可以;运行时数据区域的抽象性质规范更容易在各种各样的电脑和设备实现Java虚拟机。

一些运行时的数据区被一个程序线程或者其它独一无二的线程所共享,每一个java虚拟机实例都有一个方法区(method area)和堆(heap)。这些区域内运行的所有线程共享虚拟机。当JVM加载一个类文件(class文件)时,JVM会从二进制数据中解析出包含信息类型的类文件。它会把这些类的文件送到方法区里面去。当程序运行时,虚拟机将所有对象实例化到堆(heap)。

因为每个新线程启动,它有自己的电脑注册(程序计数器)和Java堆栈。如果线程正在执行Java方法(不是一个本地方法),pc寄存器的值显示为要执行下一个指令。Java堆中存储着Java线程(非原生)方法调用的状态。Java方法调用的状态包括局部变量、被调用的参数,它的返回值(如果有的话),中间的计算。本地方法调用的状态以具体实现相关的方式在本地方法栈存储着,以及可能在寄存器或其他具体实现相关的内存区域。Java堆栈由堆栈帧(帧)组成。一个堆栈帧包含一个Java方法调用的状态,说白了就是每个栈就是一个每个调用的方法。当一个线程调用一个方法时,Java虚拟机会分配一个新的栈给那个线程的方法。当方法完成时,虚拟机就会丢弃此方法的栈。Java虚拟机没有寄存器来保存中间数据值。指令集被使用在Java堆栈存储这些中间数据值。

上图中,线程1和2是执行java方法,线程3 执行本地的方法。

JVM的数据类型

Java虚拟机通过操作某些类型的数据来进行计算。这些数据类型和操作都严格定义的Java虚拟机规范。可以分为一组基本类型和引用类型。变量的原始类型保存原始值,变量的引用类型值的引用。引用值引用对象,但不是对象本身。原始值,相比之下,不参考任何东西。他们是实际数据本身。

所有原始类型的Java编程语言,除了布尔类型,其它都是是Java虚拟机的基本类型。编译器将Java源代码转换为字节码时,它使用int或字节来表示布尔值。在Java虚拟机中,错误的是由整数0和真正的任何非零的整数,业务涉及到布尔值使用int。布尔访问数组作为字节数组,尽管它们可能在堆上表示为字节数组或字段。原始类型的Java编程语言以外的布尔形成了数字类型的Java虚拟机。之间的数值类型为: byte, short, int, long, , char。与Java编程语言一样,Java虚拟机的基本类型有相同的范围。长在Java虚拟机总是像一个64位表示整数,独立于底层主机平台。Java程序员可以使用适用于Java虚拟机而不在原始类型中的returnValue类型。这种原始的类型在Java程序被使用。引用类型分为三种:类类型,接口类型和数组类型。所有三种类型值对动态创建对象的引用。class type值对类实例的引用。array type值是数组的引用,这是成熟的对象在Java虚拟机。interface type值是实现一个接口的类实例的引用。另一个值是null值的引用,这表明没有引用任何对象的引用变量。Java虚拟机规范定义了每个数据类型的值的范围,但没有定义他们的大小。bits比特数用来存储每个数据类型。

下篇将详细介绍JVM中heap,stack,method area如何工作的

JVM知识(上)的更多相关文章

  1. JVM 平台上的各种语言的开发指南

    JVM 平台上的各种语言的开发指南 为什么我们需要如此多的JVM语言? 在2013年你可以有50中JVM语言的选择来用于你的下一个项目.尽管你可以说出一大打的名字,你会准备为你的下一个项目选择一种新的 ...

  2. [转帖]【JVM 知识体系框架总结】

    [JVM 知识体系框架总结] https://www.cnblogs.com/mousycoder/p/11612448.html JVM 内存分布 线程共享数据区:方法区->类信息,静态变量堆 ...

  3. 深入理解java虚拟机JVM(上)

    深入理解java虚拟机JVM(上) 链接:https://pan.baidu.com/s/1c6pZjLeMQqc9t-OXvUM66w 提取码:uwak 复制这段内容后打开百度网盘手机App,操作更 ...

  4. JVM 线上故障排查

    JVM 线上故障排查 Linux 1.1 CPU 1.2 内存 1.3 存储 1.4 网络 一.CPU 飚高 寻找原因 二.内存问题排查 三.一般排查问题的方法 四.应用场景举例 4.1 怎么查看某个 ...

  5. 自动化预备知识上&&下--Android自动化测试学习历程

    章节:自动化基础篇——自动化预备知识上&&下 主要讲解内容及笔记: 一.需要具备的能力: 测试一年,编程一年,熟悉并掌握业界自动化测试工具(monkey--压力测试.monkeyrun ...

  6. JVM史上最全实践优化没有之一

    JVM史上最全优化没有之一 1.jvm的运行参数 1.1 三种参数类型 1.1.1 -server与-clinet参数 2.1 -X参数 2.1.1 -Xint.-Xcomp.-Xmixed 3.1 ...

  7. JVM 线上故障排查基本操作--CPU飙高

    JVM 线上故障排查基本操作 CPU 飚高 线上 CPU 飚高问题大家应该都遇到过,那么如何定位问题呢? 思路:首先找到 CPU 飚高的那个 Java 进程,因为你的服务器会有多个 JVM 进程.然后 ...

  8. JVM知识(一) 求你了,别再说Java对象都是在堆内存上分配空间的了!

    求你了,别再说Java对象都是在堆内存上分配空间的了! https://baijiahao.baidu.com/s?id=1661296872935371634&wfr=spider& ...

  9. JVM 线上故障排查基本操作

    # 前言 对于后端程序员,特别是 Java 程序员来讲,排查线上问题是不可避免的.各种 CPU 飚高,内存溢出,频繁 GC 等等,这些都是令人头疼的问题.楼主同样也遇到过这些问题,那么,遇到这些问题该 ...

随机推荐

  1. Kali-linux使用Easy-Creds工具攻击无线网络

    Easy-Creds是一个菜单式的破解工具.该工具允许用户打开一个无线网卡,并能实现一个无线接入点攻击平台.Easy-Creds可以创建一个欺骗访问点,并作为一个中间人攻击类型运行,进而分析用户的数据 ...

  2. 无网络环境下使用docker加载镜像

    无网络环境下使用docker加载镜像 你需要做的主要有3步骤:   先从一个有网络的电脑下载docker镜像 [root@localhost ~]# docker pull hub.c.163.com ...

  3. PAT——1066. 图像过滤

    图像过滤是把图像中不重要的像素都染成背景色,使得重要部分被凸显出来.现给定一幅黑白图像,要求你将灰度值位于某指定区间内的所有像素颜色都用一种指定的颜色替换. 输入格式: 输入在第一行给出一幅图像的分辨 ...

  4. nRF5 SDK for Mesh(二) Getting started 快速开始

    Getting started To get started, take a look at the Light switch demo. It shows how a simple applicat ...

  5. HTML和CSS基础知识

    html基本结构<html>内容</html> html开始标记<head>内容</head> html文件头标记<title>内容< ...

  6. 基于Python在MacOS上安装robotframework-ride

    基于Python在MacOS上安装robotframework-ride https://www.jb51.net/article/153665.htm https://www.jianshu.com ...

  7. iOS:时间相关(18-10-13更)

    先整理出时间相关的程序,以后有空再写成单例. 1.日历(NSCalendar) 2.时间格式() 3.时间戳 附录: 1.定时器 1.日历(NSCalendar) 1.想要获取 世纪.年.月.日.时. ...

  8. dispatch 之 常见函数小结

    你好2019!一起努力呀! 直奔主题 1.dispatch_barrier_async VS  dispatch_barrier_sync Barrier blocks only behave spe ...

  9. bootstrap世界探索2——万物的起源(网格系统)

    万物的起源是非常神奇的,谁又能想到小小的细胞(文字排版)竟能构建大千世界. <!DOCTYPE html> <html lang="en"> <hea ...

  10. 将变量做为一个对象的key,push新增进一个数组

    var orgnIdListValue=["0","2"]; function arrayField(a,b){ let arrayMes=[]; for(va ...