转行学java之前,总是听着大佬们说着java像个渣男一样可以跨平台,一次编译到处运行,瞬间,我就坚定了学java的信念,哎呀妈呀,得劲。真的学java之后,好像渣男也不是那么好学的,尤其这货的必杀技,各年龄段(操作系统)通杀太难了,这可激起了我的小暴脾气,还有能难倒小灏哥的,终于在我兢兢业业的努力下,发现了一个道理,还真有。随着慢慢攻克,看书,看看视频课,也了解了些皮毛,写出来当做个笔记吧。

学习的第一步,就是去oracle官网下载,下载完打开发现有俩目录jdk和jre,这就尴尬了,我要学的不是jvm虚拟机吗,我要学的不是他那处处可留情的必杀技吗,咋越整越多了,这三个东西困扰了我很久,背过,半个月就忘,这可咋整,我可是要当海贼王的男人,怎么能被区区jvm,jdk,jre难倒呢,耳边响起了某位大佬的二字真言:理解。背是行不通了,再花点时间钻研钻研吧。先百度瞅瞅:

jvm:Java Virtual Machine(java虚拟机)

jre:Java Runtime Environment(java运行环境)

jdk:java development kit (java开发工具包)

还是没太搞懂是啥,先看一下java下载下来的jdk和jre有啥吧,先打开jdk,

里面有一些目录和文件,其中一个好像很熟悉的样子-----jre,咦,这个不是在外层目录吗,难道他会瞬移,退回上级目录:

还好,他还在,点开两个jre:

基本上是一样的,我就猜这jdk是不是就是包含jre的呢,不然这oracle官网下载下来的东西,还能有问题?

这时候,大牛们就该读源码了,而我则继续百度,发现了一张图:

这张图应该是比较全面了,我们通常说的jdk是包含jre的,而通常说的jre是包含jvm的,jvm运行在os操作系统之上,而像一些开发工具,则是在这jdk基础之上,做了更多的完善,让我们更方便的去开发代码。

了解了他们的关系之后,再逐一了解他们的功能:

大家应该都知道,jvm是个渣男,他可不只是java的jvm,很多语言都可以在jvm上运行,只要你可以编译成class文件,我都可以任你在我的肉体上运行,它的最大功能也就是解释执行class文件。

jre比起jvm来说,稍微收敛一点,他包含了运行class文件需要的类库,他虽然也渣,但是好歹是知道老婆还是java,只不过背地里在什么系统上鬼混就说不准了。

jdk对于java开发来说,最直接面对的,也是最熟悉的,jdk包含了jre,是我们开发用的,其实没有jdk也能运行程序了,但是作为一个开发,没有jdk,你写的代码不能编译成class也没用。

我们现在也算是知道这三个渣男有啥关系,分别有啥用,对于学习java虚拟机来说,也算是打过招呼了,那么接下来,就先深入了解一下jvm的内存是怎么划分的:

线程私有区域:本地方法栈,虚拟机栈,程序计数器

线程共享区域:方法区,堆,运行时常量池

直观点的可以看下上面的内存区域图,细心点的会发现,这个图比我上面写的多了一个叫直接内存的灰色地带,他可是不被外界承认的备胎,他不属于运行时数据区,但是却又经常会用到他,备胎功底雄厚,后面介绍完了这些正牌,也介绍一下他。

虚拟机栈:

首先来聊一下虚拟机栈,大家都知道,栈的数据结构是先进后出,每个线程都会有自己的一块虚拟机栈,虚拟机栈里面是一个个的栈帧,在每次方法调用时,就会创建一个栈帧并将对应的栈帧压栈,方法执行完出栈,就这样跟着方法调用的节奏频繁的一进一出,在设计的时候,也是考虑了方法调用的模型。

栈帧里面主要包含局部变量表,操作数栈,动态连接和返回地址:

局部变量表: 用来存放八大基本类型和局部变量对象引用的地方,我们在方法执行的时候,传参、定义的局部变量都会存放到这里,供计算时,操作数栈存取,它是一个32位的长度,一般的32位也可以放的下,放不下的,占64位的高低位存放。

操作数栈:在执行计算操作时,会从局部变量表里面获取数据(可以使任意java数据类型)放到操作数栈,然后计算完成再从操作数栈移除,并存入局部变量表。

动态连接:这货有点牛,java从入门到放弃都知道这个-->多态,后面聊动态分派时会详细聊到。

返回地址:正常调用程序计数器的返回地址作为返回,具体操作:

1.恢复局部变量表和操作数栈

2.返回值压入调用者操作数栈

3.调整程序计数器指向下一个命令处

其实这一块理解不够透彻的可以想象一下方法的调用,比如我在一个方法里面调用另一个方法,我在方法调用完成出来之前首先要将这个栈帧的数据清掉,返回值自然是外层方法要用到的了,然后呢,就要调用下一步了,自然要调整程序计数器的指向。

异常返回通过异常处理器表来确定。

程序计数器:

    上面说了,程序计数器是线程私有的,他是记录了当前线程执行的字节码行号地址,由于 Java 是多线程语言,当执行的线程数量超过 CPU 核数时,线程之间会根据时间片轮询争夺 CPU 资源。如果一个线程的时间片用完了,或者是其它原因导致这个线程的 CPU 资源被提前抢夺,那么这个退出的线程就需要单独的一个程序计数器,来记录下一条运行的指令,如果没有程序计数器的保证,线程无法保证当前程序顺序执行。

    相比于普通方法,native方法是特殊的,他的执行是不是jvm具体管理的,所以jvm的程序计数器在执行native方法的时候,一直保持为空,它的调用是操作系统层面的程序计数器来记录的。

 本地方法栈:

      跟虚拟机栈没啥区别,虚拟机栈执行普通方法,本地方法栈执行native方法

上面介绍完了线程私有的jvm内存区域划分,其实对于线程私有的对于天生多线程的java,是否也是一个天生线程安全的方式呢,由jvm自行处理,又不用加锁就可以实现线程安全,我觉得也是我们在设计线程安全需要考虑的方向吧。

接下来开始介绍线程共享的,首先来介绍方法区:

方法区:

       方法区是线程共享的,他主要存储类的结构信息,运行时常量池(1.8以后放到堆里面了,但其实他的定位应该还是属于方法区的范畴),构造函数,方法数据等,总的来说其实就是存放初始化时需要用到的数据。

方法区和永久代以及元空间是很容易搞混的,尤其是永久代和方法区,其实方法区相当于是jvm对内存的逻辑划分,而永久代和元空间是jdk1.7以前和jdk1.81以后分别对方法区的不同实现,我们以前用过jdk1.6版本,公司很抠门,都是2G的内存,使用默认的配置经常会出现 java.lang.OutOfMemoryError: PermGen异常,相信这个异常很多人都很熟悉,其实这个就是永久代内存溢出,而现在,我们一般都用16g内存,而且jdk1.8之后的元空间不设置参数只受本机内存的限制,想要体验一下的同学可以在vm参数加上-XX:MaxMetaspaceSize=1M,就能很快看到OutOfMemoryError: Metaspace,可见两者实现还是不一样的。

看到这里,oracle官方为啥要将永久代弃掉而改用元空间呢,首先按官方来说,是为了融合HotSpot和JRockit,因为JRockit没有永久代,其次的话,永久代必须要配置分配空间,而太小很容易内存溢出,太大又太占空间,为其分配多少内存很难确定(永久代的大小依赖因素太多,如常量池大小,方法的大小,class等)永久代在每次FullGc都可能呗回收,而回收率很低,而元空间存储在本地内存,不需要考虑这么多。

运行时常量池:

        运行时常量池就是用来将class常量池的符号引用转为直接引用。

堆:

      堆是jvm上最大的一块区域,也是我们后面聊到的垃圾回收器GC主要光顾的地方,因为我们几乎所有的对象(几乎是因为会存在栈上分配以及八大基本对象等,但这些毕竟是小部分)都在堆中,堆给人的感觉就是个沙盘,承载了那么多的对象就像是一个个沙兵,而这些对象的引用就像是一根根连接沙兵的线都放在栈上(结合上面说的其实就是放到局部变量表里,这时候就有问题了,局部变量表是线程私有的,那我们常说的线程安全还需要考虑吗,其实就是因为这边存放的是引用,别的线程也拿到一个引用指向这个对象,那还不是随便改),栈就像是个军师一样,在沙盘上指点着干掉这个引用,垃圾回收器回收的时候就会把这些对象给干掉(当然不止这么简单,垃圾回收后面也会细讲)。

直接内存:

        直接内存又叫堆外内存,jvm运行时会首先申请一块块内存,分配给堆、栈、方法区等,而jvm没有申请的内存,就是直接内存,其实就是jvm管不到的地方,很神奇哈,jvm管不到的地方,为啥要了解呢,因为随着java生态的发展,我们不仅仅要用好申请的资源,没申请的有机会也要用好,提升资源的利用率,比如说使用NIO的话,就会频繁用到这一块,可以用java的directByteBuffer 对象操作,也可以用-XX:MaxDirectMemorySize来设置它的大小。

这一篇简单介绍了一下jvm的轮廓,相信看完之后,对jvm大体上有一个全面的了解了吧,jvm是是比较基础的知识,枯燥无味,很多东西看不见,摸不着,平时可能还用不到,但学好java,还是必须要有这方面的基础的,希望看到我文章的有缘人一起学习,共同进步吧。

.tb_button { padding: 1px; cursor: pointer; border-right: 1px solid rgba(139, 139, 139, 1); border-left: 1px solid rgba(255, 255, 255, 1); border-bottom: 1px solid rgba(255, 255, 255, 1) }
.tb_button.hover { borer: 2px outset #def; background-color: rgba(248, 248, 248, 1) !important }
.ws_toolbar { z-index: 100000 }
.ws_toolbar .ws_tb_btn { cursor: pointer; border: 1px solid rgba(85, 85, 85, 1); padding: 3px }
.tb_highlight { background-color: rgba(255, 255, 0, 1) }
.tb_hide { visibility: hidden }
.ws_toolbar img { padding: 2px; margin: 0 }

java虚拟机入门(一)-jvm基础的更多相关文章

  1. Java虚拟机学习笔记——JVM垃圾回收机制

    Java虚拟机学习笔记——JVM垃圾回收机制 Java垃圾回收基于虚拟机的自动内存管理机制,我们不需要为每一个对象进行释放内存,不容易发生内存泄漏和内存溢出问题. 但是自动内存管理机制不是万能药,我们 ...

  2. Java虚拟机内存管理原理基础入门

    Jdk:Java程序设计语言.Java虚拟机.Java API类库. Jdk是用于支持Java程序开发的最小环境. Jre:Java API类库中的Java SE API子集.Java虚拟机. Jre ...

  3. Java虚拟机详解----JVM常见问题总结

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  4. 【java虚拟机系列】java虚拟机系列之JVM总述

    我们知道java之所以能够快速崛起一个重要的原因就是其跨平台性,而跨平台就是通过java虚拟机来完成的,java虚拟机属于java底层的知识范畴,即使你不了解也不会影响绝大部分人从事的java应用层的 ...

  5. 深入理解java虚拟机(1)走进jvm

    1.JDK:java程序设计语言.java虚拟机.javaAPI 二.自动内存管理机制 ----------------------------------------------------- 1. ...

  6. java虚拟机入门(二)-探索内存世界

    上节简单介绍了一下jvm的内存布局以及简单概念,那么对于虚拟机来说,它是怎么一步步的让我们能执行方法的呢: 1.首先,jvm启动时,跟个小领导一样会根据配置参数(没有配置的话jvm会有默认值)向大领导 ...

  7. java虚拟机参数设置 jvm参数设置

    java进程命令行使用方式如下: java [-options] class [args...] -options 表示虚拟机的启动参数, class为带有main()函数的java类的全名称 arg ...

  8. Java虚拟机详解----JVM内存结构

    http://www.cnblogs.com/smyhvae/p/4748392.htm 主要内容如下: JVM启动流程 JVM基本结构 内存模型 编译和解释运行的概念 一.JVM启动流程: JVM启 ...

  9. 【深入Java虚拟机】一 JVM类加载过程

    首先Throws(抛出)几个自己学习过程中一直疑惑的问题: 1.什么是类加载?什么时候进行类加载? 2.什么是类初始化?什么时候进行类初始化? 3.什么时候会为变量分配内存? 4.什么时候会为变量赋默 ...

随机推荐

  1. C# Wpf 文件保存对话框

    C# Wpf库中无文件保存对话框,需引用winform,引用winform后多处提示引用不明确,将winform引用改别名. // 引用winform,改别名 using Forms = System ...

  2. 【终极版】利用阿里云云解析API实现动态域名解析(ddns),搭建私有服务器【含可执行文件和源码】

    前言:懒人可以直接往下看,有代码和全部资源可以下载.此文章是先前文章的定时版,主要是添加了定时执行的功能,并且将代码中的配置项放置到了app.config文件中,方便不懂开发的朋友修改使用.未经许可请 ...

  3. IQueryable的简单封装

    IQueryable的简单封装 前言 前两天在园子上看到一个问题 半年前我也考虑过这些问题,但由于这样那样的问题,没有尝试去解决. 后来公司用上了 abp vnext ,然后有一部分代码可以这样写 p ...

  4. 痞子衡嵌入式:MCUXpresso IDE下SDK工程导入与workspace管理机制

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是MCUXpresso IDE下SDK工程导入与workspace管理机制. MCUXpresso IDE是恩智浦软件团队倾注很大心血研发 ...

  5. San Francisco Crime Classification非数值性多分类问题

    给出了旧金山以往犯罪活动的相关信息,预测特定条件下的犯罪情况 分析数据集和测试集信息: 训练集给出的信息有: 1.Dates:时间日期和时间,这里考虑时间对犯罪活动有影响,日期和下边的周几有相似处,取 ...

  6. 【探索之路】机器人篇(2)-ROS系统并创建工作空间和项目

    在ROS官网,已经给出了详细的教程.下面我就般一下砖,把相应的操作写到这里.官方网址:http://wiki.ros.org/cn/ 安装ROS系统 indigo在ubuntu上的安装教程.官网:ht ...

  7. linux学习之--虚拟机安装linux【centerOS】

    计划把学习中的软件安装使用记录下来,以下是使用VMware 按照 Linux 使用桥接网络虚拟机和windows中都有不同的ip地址

  8. PostgreSQL使用MySQL外表(mysql_fdw)

    postgres使用mysql外表 转载请注明出处https://www.cnblogs.com/funnyzpc/p/14223167.html 浅谈 postgres不知不觉已经升到了版本13,记 ...

  9. excel字符串拼接

    函数:CONCATENATE() 参数可以是文本值.数字或单元格引用. 文本值和数字使用双引号括住,单元格引用直接使用.例如 =CONCATENATE("abc",A2),设A2为 ...

  10. JButton的常用方法

    JButton 实现了普通的三态外加选中.禁用状态,有很多方法可以设置,不要自己去写鼠标监听器.setBorderPainted(boolean b)    //是否画边框,如果用自定义图片做按钮背景 ...