JVM知识(一):基础原理
学过java知识和技术人,都应该听说过jvm,jvm一直是java知识里面晋级阶段的重要部分,如果想要在java技术领域更深入一步,jvm是必须需要明白的知识点。
本篇来讲解jvm的基础原理,先来熟悉一下大致的流程:
JVM运行流程:
我们都知道java一直宣传的口号:一次编译,到处运行。也是它的跨平台性。这点的具体实现如下:
java程序在经过一次编译之后,会将java代码编译成java字节码,也就是class文件。然后在不同的机器中依靠不同的java虚拟机来解析。
最后再转换为不同平台的机器码,最终得到执行。
这样,我们就可以大胆的推测说,如果我们要在mac系统中执行,是不是就只需要安装一个mac的java虚拟机就可以执行java程序了。
了解了这个基本原理后,那一个普通的java程序它的执行流程到底是怎样的?例如以下的代码。
package helloWorld;
public class HelloWorld {
public static void main(String[] args) {
System.out.print("hello world");
}
}
这段程序从编译到运行,最终打印出“Hello world”中间经过了哪些步骤,如下图;
java代码通过编译之后生成字节码文件(class文件),通过 java hello world执行,此时java会根据系统的版本找到jvm.cfg,它会根据系统版本放在不同的位置,我的在E:\SVN_ROOT\UMP_PROJECT\UMP1.0.0.0\14tools\jdk1.6.0_02\jre\lib\i386
打开可以看到:
其中-server KNOWN就表示名称为server的jvm可用,此时在电脑中搜索下jvm.dll文件,会发现是在某个server目录下。
E:\SVN_ROOT\UMP_PROJECT\UMP1.0.0.0\14tools\jdk1.6.0_02\jre\bin\server
简而言之就是通过jvm.cfg文件来找到对应的jvm.dll。这个jvm.dll文件就是java虚拟机的主要实现。
接下来会初始化jvm,并且获取JNI接口。
什么是JNI接口,就是java的本地接口(java不太好实现的与硬件或者操作系统相关的方法,一般是其他语言编写的。)。
也就是说java被编译成了class文件,jvm要通过这个JNI接口从硬盘上找到这个文件并装载到jvm里面。然后找到main方法执行。
JVM 基础结构:
在上面的例子上,我们已经知道了java程序大致的流程,但是jvm是怎么去执行class文件的,看看以下图:
从这个结构不难看出,class文件被jvm装载以后,经过jvm的内存空间调配,最后由执行引擎完成class文件的执行。这个过程还需要其他角色模块的配合才能完成。。
jvm的内存空间
jvm的内存空间包括:方法区,java堆,java栈,本地方法栈。
方法区是各个线程共享的区域,存放类信息,常亮,静态变量。
java堆也是线程共享的区域,存放类的实例,如果一个系统创建了很多类实例,如果java堆空间不足,程序就会抛出OutOfMemoryError异常。因此java堆空间是最大的。
堆被所有的线程共享,在虚拟机启动时,我们指定的"Xmx"之类的参数就是用来指定最大堆空间的指标。
理所当然,堆也是垃圾收集器重点照顾的区域,所以堆内空间还会被不同的垃圾收集器进行进一步的细分,最有名的就是新生代、老生代的划分。
java栈是每个线程私有的区域,它的生命周期与线程相同,一个线程对应一个java栈,每执行一个方法就会往栈中压入一个元素,这个元素叫“栈帧”。
而这个栈帧中包括了方法中的局部变量,用于存放中间状态值的操作栈。如果java栈空间不足了,程序会抛出StackOverflowError异常。
本地方法栈和java栈类似,只是它用来表示执行本地方法的,本地方法栈存放的方法是调用本地方法接口,最终调用本地方法库,实现与操作系统,硬件交互的目的。
PC寄存器,其实就是控制这些类对象,方法,静态变量,他们的执行顺序。它可以看做是当前线程说执行的字节码的行号指示器。由于jvm是多线程是通过轮流浅黄并分配处理器执行时间的来方式来实现的,在任何一个确定的时刻,一个处理器(对应多核处理器来说是一个内核)都只会执行一条线程中的指令。因此为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器(PC寄存器),各条线程之间计数器互不影响,独立存储,我们称这类内存区域为“线程私有的内存”。
执行引擎就是根据PC寄存器调配的指令顺序,一次执行程序指令。
对于程序中出现OutOfMemoyError,简单的总结如下:
1、堆内存不足是最常见的OOM原因之一,抛出的错误信息是“java.lang.OutOfMemoryError:Java heap space”,原因可能千奇百怪。
比如:可能存在内存泄露问题;也很有可能就是堆得大小不合理,比如我们要处理可观的数据量,但是没有显式指定JVM堆大小或者指定数据偏小;或者出现JVM处理引用不及时,导致堆积起来,内存无法释放等。
2、Java虚拟机栈和本地方法栈,如果我们写一段程序不断的进行地柜调用,而且没有退出条件,就会导致不断的进行压栈。类似这种情况,JVM实际会抛出StackOverFlowError;当然,如果JVM试图去扩展栈空间的时候失败,就会抛出OutOfMemoyError。
3、对于老版本的Oracle JDK,因为永久代的大小是有限的,并且JVM对永久代垃圾回收非常的不积极,所以当我们不断添加新类型的时候,永久代出现OutOfMemoyError也非常的多见,尤其是在运行时,存在大量动态类型生成的场合;类似Intern字符串缓存占用太多空间,也会导致OOM问题。对应的异常信息,会标记出来和永久代相关:“java.lang.OutOfMemoyError:PermGen space”。
4、随着元数据区的引入,方法区内存以及不再那么窘迫,所以相应的OOM有所改观,出现OOM,异常信息则变成了:"java.lang.OutOfMemoyError: Metaspace"。
结语:
本文主要介绍了java虚拟机运行的基本流程,以及java虚拟机内部结构。下一篇我们将学习java内存模型以及探索java变量的可见性、有序性、指令重排等问题以及总结了可能会发现OutOfMemoyError异常的原因和所在。
JVM知识(一):基础原理的更多相关文章
- C#基础原理拾遗——引用类型的值传递和引用传递
C#基础原理拾遗——引用类型的值传递和引用传递 以前写博客不深动,只搭个架子,像做笔记,没有自己的思考,也没什么人来看.这个毛病得改,就从这一篇开始… 最近准备面试,深感基础之重要,奈何我不是计算机科 ...
- Hadoop基础原理
Hadoop基础原理 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 业内有这么一句话说:云计算可能改变了整个传统IT产业的基础架构,而大数据处理,尤其像Hadoop组件这样的技术出 ...
- APPcrawler基础原理解析及使用
一.背景 一年前,我们一直在用monkey进行Android 的稳定性测试 ,主要目的就是为了测试app 是否会产生Crash,是否会有ANR,页面错误等问题,在monkey测试过程中,实现了脱离Ca ...
- I2C 基础原理详解
今天来学习下I2C通信~ I2C(Inter-Intergrated Circuit)指的是 IC(Intergrated Circuit)之间的(Inter) 通信方式.如上图所以有很多的周边设备都 ...
- OpenStack的基础原理
OpenStack的基础原理 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. OpenStack既是一个社区,也是一个项目和一个开源软件,它提供了一个部署云的操作平台或工具集.其 ...
- JVM 启动参数及原理 转
Java虚拟机(JVM)是Java应用的运行环境,从一般意义上来讲,JVM是通过规范来定义的一个虚拟的计算机,被设计用来解释执行从Java源码编译而来的字节码.更通俗地说,JVM是指对这个规范的具体实 ...
- DNS服务基础原理介绍
FQDN 全称域名 localhost(主机名或者是别名).localdomain(域名) FQDN=主机名.域名 根域 . 顶级域名 .com .n ...
- Sql注入基础原理介绍
说明:文章所有内容均截选自实验楼教程[Sql注入基础原理介绍]~ 实验原理 Sql 注入攻击是通过将恶意的 Sql 查询或添加语句插入到应用的输入参数中,再在后台 Sql 服务器上解析执行进行的攻击, ...
- Linux基础知识与基础命令
Linux基础知识与基础命令 系统目录 Linux只有一个根目录,没有盘符的概念,文件目录是一个倒立的树形结构. 常用的目录功能 bin 与程序相关的文件 boot 与系统启动相关 cdrom 与Li ...
随机推荐
- Android IntentFilter匹配规则
一:显式调用 需要明确指定被启动对象的组件信息,一般是在相同的应用程序内部实现的 Intent intent = new Intent(); intent.setClass(SecondActivi ...
- Java学习之路(十二):IO流<三>
复习:序列流 序列流可以把多个字节输入整合成一个,从序列流中读取到数据时,将从被整合的第一个流开始读取,读完这个后,然后开始读取第二个流,依次向后推. 详细见上一篇文章 ByteArrayOutput ...
- vue制作小程序--mpvue
mpvue是一个使用 Vue.js 开发小程序的前端框架 http://mpvue.com/ sass的使用 https://segmentfault.com/q/1010000014194954 n ...
- docker 容器启动后立马退出的解决方法
原因: 容器同时只能管理一个进程,如果这个进程结束了容器就退出了,但是不表示容器只能运行一个进程(其他进程可在后台运行),但是要使容器不退出必须要有一个进程在前台执行. 解决方案: 启动脚本最后一 ...
- Spring整合Hibernate的XML文件配置,以及web.xml文件配置
利用Spring整合Hibernate时的XML文件配置 applicationContext.xml <?xml version="1.0" encoding=" ...
- PHP初级篇
PHP初级篇 PHP环境搭建: 企业中常用到的环境是:Linux+Apache+MySQL+PHP 学习环境是:Windows+Apache+MySQL+PHP 工具 Apache 2.4.4 MyS ...
- Node.js压缩与解压数据
Node.js中提供了一个很好的库Zlib来压缩解压数据. 一.压缩缓冲区 Zlib中有下面几个函数方便解压缩缓冲区. gzip/gunzip:标准gzip压缩. deflate/inflate:基于 ...
- spark集群搭建(java)未完待续
环境 操作系统:windows10 虚拟机工具:VMware14.1 NUX版本:Centos7.2(64) JDK:1.8(64) 一.安装linux,master(桥接模式上网),slave(na ...
- SpringBoot+Mybatis整合入门(一)
SpringBoot+Mybatis 四步整合 第一步 添加依赖 springBoot+Mybatis相关依赖 <!--springBoot相关--> <parent> < ...
- git相关的简单命令
初次使用建议看这个ppt:http://www.bootcss.com/p/git-guide/ 从现有仓库克隆 这需要用到 git clone 命令.如果你熟悉其他的 VCS 比如 Subve ...