学过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知识(一):基础原理的更多相关文章

  1. C#基础原理拾遗——引用类型的值传递和引用传递

    C#基础原理拾遗——引用类型的值传递和引用传递 以前写博客不深动,只搭个架子,像做笔记,没有自己的思考,也没什么人来看.这个毛病得改,就从这一篇开始… 最近准备面试,深感基础之重要,奈何我不是计算机科 ...

  2. Hadoop基础原理

    Hadoop基础原理 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 业内有这么一句话说:云计算可能改变了整个传统IT产业的基础架构,而大数据处理,尤其像Hadoop组件这样的技术出 ...

  3. APPcrawler基础原理解析及使用

    一.背景 一年前,我们一直在用monkey进行Android 的稳定性测试 ,主要目的就是为了测试app 是否会产生Crash,是否会有ANR,页面错误等问题,在monkey测试过程中,实现了脱离Ca ...

  4. I2C 基础原理详解

    今天来学习下I2C通信~ I2C(Inter-Intergrated Circuit)指的是 IC(Intergrated Circuit)之间的(Inter) 通信方式.如上图所以有很多的周边设备都 ...

  5. OpenStack的基础原理

    OpenStack的基础原理 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   OpenStack既是一个社区,也是一个项目和一个开源软件,它提供了一个部署云的操作平台或工具集.其 ...

  6. JVM 启动参数及原理 转

    Java虚拟机(JVM)是Java应用的运行环境,从一般意义上来讲,JVM是通过规范来定义的一个虚拟的计算机,被设计用来解释执行从Java源码编译而来的字节码.更通俗地说,JVM是指对这个规范的具体实 ...

  7. DNS服务基础原理介绍

    FQDN 全称域名 localhost(主机名或者是别名).localdomain(域名)    FQDN=主机名.域名 根域               . 顶级域名       .com   .n ...

  8. Sql注入基础原理介绍

    说明:文章所有内容均截选自实验楼教程[Sql注入基础原理介绍]~ 实验原理 Sql 注入攻击是通过将恶意的 Sql 查询或添加语句插入到应用的输入参数中,再在后台 Sql 服务器上解析执行进行的攻击, ...

  9. Linux基础知识与基础命令

    Linux基础知识与基础命令 系统目录 Linux只有一个根目录,没有盘符的概念,文件目录是一个倒立的树形结构. 常用的目录功能 bin 与程序相关的文件 boot 与系统启动相关 cdrom 与Li ...

随机推荐

  1. kafka 消费者offset记录位置和方式

    我们大家都知道,kafka消费者在会保存其消费的进度,也就是offset,存储的位置根据选用的kafka api不同而不同. 首先来说说消费者如果是根据javaapi来消费,也就是[kafka.jav ...

  2. 搭建互联网架构学习--005--框架初步拆分ssm单一框架

    经过前边的准备步骤,服务器基本搭建完毕,接下来就开始一步步搭建框架了. 拆分单一结构:拆分的目的是为下一步引入dubbo做准备的. 把下边这个单一maven框架进行拆分 这个就是一个简单的maven项 ...

  3. Android_读取元素的数据

    在AndroidManifest.xml中,<meta-data>元素可以作为子元素,被包含在<activity>.<application> .<servi ...

  4. sql 时期格式整理

    我们经常出于某种目的需要使用各种各样的日期格式,当然我们可以使用字符串操作来构造各种日期格式,但是有现成的函数为什么不用呢? SQL Server中文版的默认的日期字段datetime格式是yyyy- ...

  5. traefik+etcd构建grpc微服务demo

    1.下载安装traefik https://github.com/containous/traefik/releases 2.下载安装etcd3 https://github.com/coreos/e ...

  6. test11

    -Xms512m-Xmx512m-XX:PermSize=512-XX:MaxPermSize=512

  7. springcloud-03-服务注册

    新建一个 provider-user 和consumer-movie, user为服务提供者, movie为服务的消费真, 没有什么难的, 直接上代码 microserver-provider-use ...

  8. WINCRIS的使用

    附件下载:http://pan.baidu.com/s/1sj7EsOH 1.首先大家先到官网上下载自己的BIOS , 准备一个U盘格式化成FAT/FAT32格式. (网上说U盘的大小不要超过2G,这 ...

  9. php的304方式

    一般浏览器请求php是不会被缓存的,除非php直接显示的发送head 304 if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) { $browserCache ...

  10. [笔记] Python 中JSON数据的读写

    前言 JSON(JavaScript Object Notation,JavaScript对象表示法)是一种轻量级的数据交换语言 JSON是独立于语言的文本格式, JSON 数据格式与语言无关 JSO ...