JVM 深入理解(一)

简介:
Java Virtual Machine JVM 全称 Java Virtual Machine,也就是我们耳熟能详的 Java 虚拟机。它能识别 .class后缀的文件,并且能够解析它的指令,最终调用操作系统上的函数,完成我们想要的操作。
翻译:Java 程序不一样,使用 javac 编译成 .class 文件之后,还需要使用 Java 命令去主动执行它,操作系统并不认识这些 .class 文件。所以JVM就是一个翻译。
image.png
从图中可以看到,有了 JVM 这个抽象层之后,Java 就可以实现跨平台了。JVM 只需要保证能够正确执行 .class 文件,就可以运行在诸如 Linux、Windows、MacOS 等平台上了,JVM讲.class和.jar进行翻译成操作系统能识别的机器码,从而调用操作系统的方法。
JVM、JDK,JRE之间的关系:
JVM:只是一个翻译,把Class翻译成机器识别的代码,JVM 不会自己生成代码,需要大家编写代码,同时需要很多依赖类库,这个时候就需要用到JRE。(翻译)
JRE:它除了包含JVM之外,提供了很多的类库(就是我们说的jar包,它可以提供一些即插即用的功能,比如读取或者操作文件,连接网络,使用I/O等等之类的)这些东西就是JRE提供的基础类库。JVM 标准加上实现的一大堆基础类库,就组成了 Java 的运行时环境,也就是我们常说的 JRE(Java Runtime Environment)。(提供类库)
JDK:提供了一些非常好用的小工具,比如 javac(编译代码)、java、jar (打包代码)、javap(反编译<反汇编>)等。这个就是JDK(提供工具)
JVM整体流程图:
流程图.png
图中的运行时数据区:jvm所管理的内存。
执行引擎:将放在运行时数据区的中的方法,和操作进行解释执行。
解释执行与JIT之间的区别:
以HelloWord.java为例,通过javac进行编译之后得到.class文件,通过ClassLoader进行类加载到运行时数据区中(jvm所管理的内存),jvm再通过执行引擎将运行时数据区中的数据进行翻译机器码,从而执行调用操作系统的方法。那么还是没有说到解释执行和JIT 呢?
翻译:
(1)、将所有的类都全部翻译成机器码之后才执行,(速度慢,效率低)
(2)、一遍翻译一遍执行,(相比第一种速度上有了很大的提升)-----解释执行。
那什么又是JIT呢?
在hotspot中,可能会有热点方法,如我们同一个方法执行很多次,jvm会将这部分代码直接编程成本地代码,提高运行速度,(前提是热点方法,热点类)
运行时数据区:
运行时数据区的定义:
Java虚拟机在执行Java程序 的过程中会把它所管理的内 存划分为若干个不同的数据 区域。
运行时数据区的类型:程序计数器、虚拟机栈、本 地方法栈、Java堆、方法区 (运行时常量池)、直接内存。
如图所示:
image.png
1、程序计数器:当前线程执行的字节码的行号指示器;各线程之间独立存储,互不影响。
举个例子:现有一个Person类,Person中提供了对应的方法,通过javac编译之后得到对应的.class文件,现在通过javap -c 对.class 文件进行反编译,如图所示:
image.png
上图所示是通过反编译得到.class文件的对应的字节码,每行都有对应的编号,在多线程中,cpu调度线程的,时间轮转时线程通过程序计数器记录当前的对应的行号,直到线程下次拥有cpu调度时接着执行,从而确保程序的正常执行。
2、虚拟机栈:存储当前线程运行方法所需的数据,指令,返回地址,栈(先进后出)
2.1、栈帧(方法)
2.1.1、局部变量表:用来存储局部变量 只能 存储8大基本类型,对象引用
2.1.2、操作数栈:存放方法的操作、执行。
2.1.3、动态链表::Java语言特性多态(需要类运行时才能确定具体的方法)。
2.1.4、完成出口:正常返回(调用程序计数器中的地址作为返回)、异常的话(通过异常处理器表<非栈帧中的>来确定)
3、方法区:
方法区主要存储:类信息,常量,静态变量,即时编译期编译后的代码。
4、堆:
堆主要存储:几乎所有对象实例,数组。
方法区和堆为啥不用一个区域,要用两个区域?堆可以进行频繁的回收,方法区回收比较难,动静分明。
从底层深入理解运行时数据区:
image.png
1、申请内存,分别给堆,栈,方法区分配内存。
2、类加载,class进入方法区。
3、常量,静态变量 入方法区。
4、虚拟机栈帧--入栈帧
下面先介绍一下HSDB工具,查看内存的工具:
1)、首先找到jdk的安装目录,找到sawindbg.dll文件,将改文件复制到对应目录的jre下。
image.png
2)、现在采用JVMObject.java为例:
public class JVMObject {
    public final static String MAN_TYPE = "man"; // 常量
    public static String WOMAN_TYPE = "woman";  // 静态变量

    public static void  main(String[] args)throws Exception {//栈帧
        Teacher T1 = new Teacher();//堆中   T1 是局部变量
        T1.setName("Mark");
        T1.setSexType(MAN_TYPE);
        T1.setAge(36);
        for (int i=0;i<15;i++){//进行15次垃圾回收
            System.gc();//垃圾回收
        }
        Teacher T2 = new Teacher();
        T2.setName("King");
        T2.setSexType(MAN_TYPE);
        T2.setAge(18);
        Thread.sleep(Integer.MAX_VALUE);//线程休眠很久很久
    }
}

class Teacher{
    String name;
    String sexType;
    int age;//堆

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    public String getSexType() {
        return sexType;
    }
    public void setSexType(String sexType) {
        this.sexType = sexType;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}
3)、在jdk下面的lib目录找到a-jdi.jar文件,输入命令如下:
image.png
4)、让JVMObject运行,再将环境切换到JVMObject对应的目录下输入命令如下所示:
image.png
5)、在HSDB输入框中输入JVMObject对应的10756,并点击main方法
image.png
image.png
如图所示为jvm虚拟机的栈区图,左边对应的是内存的地址。
image.png
main方法对应栈帧的内存地址,图上怎么还会有一个栈帧?原因是在代码中还调用了sleep方法,查看 sleep源码属于本地方法,验证了本地方法栈和hotspot栈合并。
再看class在内存中所在的区域
image.png
image.png
通过点击Teacher可以看到有两个地址,在回看JVMObject代码,在代码中创建了两个对象,mark和king对象。为了验证随便点击一个进行查看:
image.png
接下来看看堆空间
image.png
从图上可以看出,分为两个空间,新生代,和老年代,并且内存地址还是连续的,JVMOject代码中mark对象通过调用gc进行回收15次,则mark对象进入了老年代,而king在新生代。
image.png
总结:
以栈帧的方式存储方法调用的过程,并存储方法调用过程中基本数据类型的变量(int、short、long、byte、float、double、boolean、char等)以 及对象的引用变量,其内存分配在栈上,变量出了作用域就会自动释放; 而堆内存用来存储Java中的对象。无论是成员变量,局部变量,还是类变量,它们指向的对象都存储在堆内存中。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,284评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,115评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,614评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,671评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,699评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,562评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,309评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,223评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,668评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,859评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,981评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,705评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,310评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,904评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,023评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,146评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,933评论 2 355