java虚拟机学习高级篇

还是继续说一下java虚拟机,为什么呢?因为我随意翻着别人的博客一不小心看到有关jvm的一点新的东西,挺有趣的,就按照我的理解分享一下;

还记得以前学过一首诗,“看成岭侧成峰,远近高低各不同”,这一句诗的内在含义有的时候真的会让你猛然惊醒,进而如获至宝!的确,有的时候换一个角度看问题,你会发现不一样的世界。

我们平常学java的时候肯定涉及到了进程,多线程的概念,但是有没有想过操作系统也有进程和线程的概念,两者有关系吗?假如我们视角放高一点,以操作系统的角度看看一个java程序的运行,又会是什么样子的呢?jvm在将字节码文件翻译成机器码之后怎么会调用cpu呢?自己调用的还是假借了谁的手呢?jvm在操作系统中到底扮演着一个什么角色呢?还有最基本的一个问题,操作系统是什么?

下面我们就来把这些东西整个的给串一下,当然,具体的细节还要每个人自己去研究;

1.简单看看操作系统

水平有限,不可能对操作系统理解得那么透彻,只是说说我自己的理解吧!

一说起操作系统大家肯定既陌生又贼熟悉,为什么呢?因为我们经常使用操作系统,比如windows系列,unix系列,macos等等,我们每天一打开电脑首先就会自动启动一个操作系统,但是又有几个人真的能了解透彻操作系统呢?我们总是在操作系统中用着几个最常见的应用,qq、LOL、淘宝、360、优酷等等软件,然而我们却很少关注操作系统到底能干什么,假如没有操作系统会怎么样?

我们现在用的所有计算机结构都是由冯•诺依曼计算机演变过来的,下面我们简单看看冯诺依曼计算机结构:

我们可以看看,我们使用电脑基本就是用这几部分,有这几部分足够我们运行一个程序了啊!那么,我们需要操作系统干嘛呢?

首先我们要考虑到一点,由于运算器是能识别二进制码,所以我们在输入设备中只能输入很多很多的0和1组成的代码,这样的代码简直就是一股泥石流,让人绝望,然而早期的计算机还就是这样编程的,通过我们人工的方式写很多的0和1去对那些屏幕、cpu等硬件的驱动程序(比如声音驱动、显卡驱动,再驱动程序再底层其实就是用高低电位去使得硬件发生变化)发出指令进行操作;这个时候可没有什么线程什么的,没有cpu等待时间什么的,可想而知效率感人!

在操作系统没有出来的时候编程真的很痛苦,一般人真干不了!过了很多年之后,终于有了操作系统,操作系统本质上是一个软件,我们可以简单的把操作系统看作是对这些驱动的封装,在操作系统内部(可以叫做内核)提供了两类接口,一类是只要那些硬件驱动程序实现了这些接口,操作系统就通过这些接口使用那些硬件设备;然后另一类接口就是给我们程序员去实现的,我们只需要面向这些接口编程我们就可以间接的操作硬件!

而我们熟悉的JVM就是实现了操作系统提供的给程序员实现的那一类接口,而JVM又向JAVA程序员提供了一些java api,我们只需要按照java api就能间接的通过jvm对操作系统进行控制,进而对驱动发指令,最后就是可以对那些硬件中的数据进行处理;

于是我们可以看看下面这个图(暂时忽略UNIX命令和库),这个图中用户编写的应用程序可以看作是JVM,JVM可以根据操作系统提供的系统调用接口对操作系统内核发出一些指令,内核就会调用硬件的驱动程序对硬件进行一些操作,比如读取文件数据、向文件中写入数据等等

由于操作系统提供了这么强大的功能,于是我们现在几乎所有的编程语言都是在操作系统的基础上进行编程,然后通过解释器这类东西将我们写的程序转化为计算机能够识别的机器码,然后调用操作系统接口,最终实现对硬件的操作。

顺便一提,这里用户编写的应用程序我们就可以看作是QQ,优酷,酷狗音乐等等软件,如果是单核cpu,你同时打开多个应用,那么cpu会来回在多个应用切换,只是由于切换时间太短,我们感觉不到,还以为是同时运行的!就好像电影,其实电影是一张张图每隔零点几秒进行翻页,但是我们眼睛察觉不出来,还有我们鼠标移动在屏幕上移动,为什么这么流畅呢?因为我们的屏幕每隔零点几秒就刷新一次,当然我们察觉不出来。

现在我们看看操作系统的定义:是一组控制和管理计算机硬件和软件资源,合理对各类作业进行调度,以及方便用户的程序的集合”,是不是有点懂了,我们继续往下看!

2.操作系统的内存结构

我们可以简单看看操作系统的内存结构,一般查资料我们看到的是下图这样的,我们肯定看不懂!玛德,这都是什么鬼,除了那个栈和堆其他的都不知道干嘛的!

于是我们可以稍作修改,去掉一些不利于我们理解的东西,如下图所示,是不是就熟悉了一点了,貌似跟jvm的内存结构很像啊!!!

我们把硬盘和操作系统的PC寄存器添加上去试试效果,下图所示!有没有似曾相识的感觉,对的,jvm跟这个几乎一模一样,这里的硬盘其实就是相当于jvm的方法区(方法区也叫做永久代,看名字就知道是可以永久保存的啊!),还有jvm中的本地方法栈不在jvm的内存结构中,原来在这里啊,其实指的就是操作系统的栈;

操作系统的PC寄存器和jvm的PC寄存器用处差不多,是记录当前CPU运行命令的地址;

3.jvm在操作系统中的角色

举个简单的例子,当我们在电脑桌面上双击了QQ,那么QQ这个应用就会启动,操作系统就会创建一个进程,然后会在操作系统的堆中为这个进程开辟空间,用于存放该进程中产生的数据;

对操作系统来说,JVM和这个QQ应用没有什么两样,一视同仁,于是我们可以得到这样的一个图:

最后我们再把jvm中的内存结构完善一下,如下图:

看到这里,我们不禁的笑了,原来jvm就是按照操作系统的样子做了一遍,假如我们站在操作系统角度看,jvm其实就是一个平常的应用;假如我们站在java字节码文件的角度看,其实jvm就相当于一个操作系统,把字节码文件放进了jvm这个虚拟操作系统的硬盘中(方法区)中,然后jvm中对方法区中的数据进行读取、创建对象等后续各种操作;

操作系统栈和jvm栈基本一样;操作系统堆和jvm堆基本也一样,但是释放内存的方式有点差异,操作系统的堆是要程序员手动释放,而jvm的堆是靠gc自动清理;

现在我们再百度一下看看jvm的定义,现在应该知道jvm是个什么东西了吧!哈哈

4.方法区中的信息

虽然我们之前简要的说了方法区中的数据就是有关于类的基本信息,静态变量和常量池,但是说得比较笼统;

现在我们再回头看看jvm方法区中存的具体是什么信息:

(1)类信息

(2)字段信息

(3)方法信息

(4)常量池

(5)静态变量

(6)一个到Class对象的引用

(7)一个到加载该类的类加载器的引用

(8)方法表(有的JVM有,有的JVM没有):这是一个数组,保存了该类在堆中创建的所有对象的实例方法的引用,但是比较耗内存,所以有的jvm设计者没有设计这个方法表;

对应的java代码如下:

public final class com.wyq.test.ClassStruct extends Object implements Serializable {//1.类信息:包括访问修饰符,全类名,父类名,实现接口等
 //2.对象字段信息:包括访问修饰符,类型,字段名
 private String name;
 private int id;

 //4.常量池:常量和一些符号引用
 public final int CONST_INT=0;
 public final String CONST_STR="CONST_STR";

 //5.静态变量
 public static String static_str="static_str";

 //3.方法信息:包括修饰符,方法返回值,方法名,局部变量,方法体(花括号中的内容)
 public static final String getStatic_str (){
  return ClassStruct.static_str;
 }}

可以清楚的看到其实方法区中保存的就是将字节码文件中的所有信息!   

5.java程序执行流程

现在我们结合操作系统的知识和上图看看我们运行一个java程序,电脑中到底是干了什么?就不考虑缓存了。。。

1.我们在Eclpse中写完一个java源程序,必须要Ctrl+S保存一下,这个动作就是将源程序保存到电脑硬盘中;

2.然后我们运行一个main方法,这个时候编译器就会将硬盘中的源程序读取到内存并编译成字节码文件(注意这个字节码文件不一定非要是本计算机编译的,只要是符合字节码文件格式的字节码文件都行,别人电脑传给你的肯定可以;这符合java一处编译到处运行的原则)

3.我们运行一个main方法的同时,对操作系统来说就是新创建了一个进程,就要在操作系统的堆中申请这个进程的内存空间,我们把这块内存空间称为JVM(注意,假如运行两个java程序那么这里就会创建两个jvm的内存空间)

4.jvm实例创建成功,就会在这个实例之中的内存空间进行分配,java栈,java堆,方法区等

5.由于类装载子系统,会把类加载器先加载到java堆中,然后类加载器根据我们的java源程序类名去指定路径中去加载字节码文件(双亲委托机制),放入方法区中

6.由执行引擎去执行这个字节码文件,伴随着验证、准备、解析和初始化,最终在java堆中生成了Class对象和实例化对象。

7.假如调用本地方法(就是Native修饰的方法)就会涉及到本地方法栈(和java栈作用差不多,压栈和弹栈),在操作系统栈中压入栈帧,假如在本地方法中还调用java中的方法,这个时候在操作系统的栈中压入一个栈帧,然后下一个栈帧却到了jvm的栈中,很有趣的一个东西。

8.我们方法调用完毕,栈中栈帧弹出,栈清理完毕;然后gc会对java堆中对象进行回收释放内存空间,然后gc还会对方法区进行清理,自此jvm中的内存空间清理完毕;

9 操作系统堆jvm进行清理,jvm进程结束。

总结:

由于对操作系统的理解还处于比较懵懂的状态,所以文中可能会有很多词语运用不当,很惭愧,以后肯定会抽个时间慢操作系统整个的学习一遍的,希望这一天不要来的太迟,哈哈哈

(0)

相关推荐

  • 作为程序员必须掌握的Java虚拟机中的22个重难点(推荐0

    Java虚拟机一直是比较重要的知识点,是Java高级开发必会的.本文为你总结了关于JVM的22个重点.难点,图文并茂的向你展示和JVM有关的重点知识.全文共7000字左右. 概念 虚拟机:指以软件的方式模拟具有完整硬件系统功能.运行在一个完全隔离环境中的完整计算机系统 ,是物理机的软件实现.常用的虚拟机有VMWare,Visual Box,Java Virtual Machine(Java虚拟机,简称JVM). Java虚拟机阵营:Sun HotSpot VM.BEA JRockit VM.IB

  • java命令调用虚拟机方法总结

    java命令调用虚拟机 java的虚拟机调用,按住Win+r命名,如图所示: 继续点击确定按钮,如图所示: 可以看到后台命令,如图所示: 调用虚拟机编译Test.java代码:如图所示: Test.java可以看到在E盘JavaTest文件夹下,,如图所示: 回到命令后台,输入:E: 按回车键,然后在输入:cd JavaTest,按回车键, 然后输入javac Test.java,按回车键,这个是调用虚拟机编程的java代码, 最后输入:java Test,按回车键,可以看到后台输出:Hello

  • java虚拟机学习笔记基础篇

    1.前言(基于JDK1.7) 最近想把一些java基础的东西整理一下,但是又不知道从哪里开始!想了好久,还是从最基本的jvm开始吧!这一节就简单过一遍基础知识,后面慢慢深入... 水平有限,我自己也是很难把jvm将清楚的,我参考一本书<深入java虚拟机第二版>(版本比较老,其实很多大佬的博客都是参考的这本书的内容...) 所谓jvm,又名java虚拟机.我们平常写java程序的时候几乎是感觉不到jvm的存在的,我们只需要根据java规范去编写类,然后就可以运行程序了,当然只有我们程序出现bu

  • 带着新人看java虚拟机01(推荐)

    1.前言(基于JDK1.7) 最近想把一些java基础的东西整理一下,但是又不知道从哪里开始!想了好久,还是从最基本的jvm开始吧!这一节就简单过一遍基础知识,后面慢慢深入... 水平有限,我自己也是很难把jvm将清楚的,我参考一本书<深入java虚拟机第二版>(版本比较老,其实很多大佬的博客都是参考的这本书的内容...),电子档pdf文件链接:https://pan.baidu.com/s/1bxs4i0gnVpz7Lkjl2fxS9g 提取码:n5ou ,有兴趣的小伙伴可以自己下载自己好好

  • java虚拟机学习笔记进阶篇

    上一节是把大概的流程给过了一遍,但是还有很多地方没有说到,后续的慢慢会涉及到,敬请期待! 这次我们说说垃圾收集器,又名gc,顾名思义,就是收集垃圾的容器,那什么是垃圾呢?在我们这里指的就是堆中那些没人要的对象. 1.垃圾收集器的由来 为什么要有垃圾收集器啊?不知道有没有想过这个问题,你说我运行一个程序要什么垃圾收集器啊? 随意看一下下面两行代码: User user = new User("root","123456") user = new User("

  • 详解Java虚拟机30个常用知识点之1——类文件结构

    1. Java文件 ClassFileTest.java package com.zxs.ssh.template.service; public class ClassFileTest { int m = 1; public int inc(){ return m+1; } } 2. Class文件ClassFileTest.class javac  ClassFileTest.java  编译.java文件得到.class文件 JDK版本  1.8.0_201 .class文件可以用WinH

  • java虚拟机学习高级篇

    还是继续说一下java虚拟机,为什么呢?因为我随意翻着别人的博客一不小心看到有关jvm的一点新的东西,挺有趣的,就按照我的理解分享一下: 还记得以前学过一首诗,"看成岭侧成峰,远近高低各不同",这一句诗的内在含义有的时候真的会让你猛然惊醒,进而如获至宝!的确,有的时候换一个角度看问题,你会发现不一样的世界. 我们平常学java的时候肯定涉及到了进程,多线程的概念,但是有没有想过操作系统也有进程和线程的概念,两者有关系吗?假如我们视角放高一点,以操作系统的角度看看一个java程序的运行,

  • java虚拟机多线程进阶篇总结

    1.线程池基本参数 以Executors.newFixedThreadPool()这种创建方式为例: 大家想象,假如你创建一个线程池,你想这个池子有些什么参数呢?首先这个池子必须要有一个最大值:然后还希望这个池子的线程数量有一个警戒线,到了这个警戒线的位置说明线程池暂时已经满了,如果这个时候还有人过来拿线程,我们就要把这些人抓起来扔到一个地方去让他们排队,告诉他们:请稍等,等我们的线程有空闲的时候再来处理你的事:再然后假如人排队的地方都满了,玛德,好多人,于是线程池就想办法东拼西凑又多搞出来了几

  • 深入理解Java虚拟机_动力节点Java学院整理

    什么是Java虚拟机 Java程序必须在虚拟机上运行.那么虚拟机到底是什么呢?先看网上搜索到的比较靠谱的解释: 虚拟机是一种抽象化的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实现的.Java虚拟机有自己完善的硬体架构,如处理器.堆栈.寄存器等,还具有相应的指令系统.JVM屏蔽了与具体操作系统平台相关的信息,使得Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行. 这种解释应该算是正确的,但是只描述了虚拟机的外部行为和功能,并没有针对内部原理

  • java 虚拟机深入了解

    什么是Java虚拟机 作为一个Java程序员,我们每天都在写Java代码,我们写的代码都是在一个叫做Java虚拟机的东西上执行的.但是如果要问什么是虚拟机,恐怕很多人就会模棱两可了.在本文中,我会写下我对虚拟机的理解.因为能力所限,可能有些地方描述的不够欠当.如果你有不同的理解,欢迎交流. 我们都知道Java程序必须在虚拟机上运行.那么虚拟机到底是什么呢?先看网上搜索到的比较靠谱的解释: 虚拟机是一种抽象化的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实现的.Java虚拟机有自己完善的硬

  • java虚拟机深入学习之内存管理机制

    前言 前面说过了类的加载机制,里面讲到了类的初始化中时用到了一部分内存管理的知识,这里让我们来看下Java虚拟机是如何管理内存的. 先让我们来看张图 有些文章中对线程隔离区还称之为线程独占区,其实是一个意思了.下面让我们来详细介绍下这五部分: 运行时数据区 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域,这些区域都拥有自己的用途,并随着JVM进程的启动或者用户线程的启动和结束建立和销毁. 先让我们了解下进程和线程的区别: 进程是资源分配的最小单位,线程是程序

  • 老生常谈Java虚拟机垃圾回收机制(必看篇)

    在Java虚拟机中,对象和数组的内存都是在堆中分配的,垃圾收集器主要回收的内存就是再堆内存中.如果在Java程序运行过程中,动态创建的对象或者数组没有及时得到回收,持续积累,最终堆内存就会被占满,导致OOM. JVM提供了一种垃圾回收机制,简称GC机制.通过GC机制,能够在运行过程中将堆中的垃圾对象不断回收,从而保证程序的正常运行. 垃圾对象的判定 我们都知道,所谓"垃圾"对象,就是指我们在程序的运行过程中不再有用的对象,即不再存活的对象.那么怎么来判断堆中的对象是"垃圾&q

  • Java笔记之从IO模型到Netty框架学习初识篇

    目录 什么是Netty IO模型 BIO BIO编程简单流程 BIO简单实例 NIO Buffer Buffer基本使用 Buffer四个主要属性 Channel 本地文件写案例 本地文件读案例 本地文件拷贝案例 Selector 什么是Netty 异步,基于事件驱动的网络应用框架,用以快速开发高性能,高可靠的网络IO程序 主要针对在TCP协议下,面向Clients端的高并发应用 本质是一个NIO框架,适用于服务器通讯等场景 异步:发送请求无需等待响应,程式接着往下走. 事件驱动:一个连接事件或

  • Java虚拟机JVM性能优化(二):编译器

    本文将是JVM 性能优化系列的第二篇文章(第一篇:传送门),Java 编译器将是本文讨论的核心内容. 本文中,作者(Eva Andreasson)首先介绍了不同种类的编译器,并对客户端编译,服务器端编译器和多层编译的运行性能进行了对比.然后,在文章的最后介绍了几种常见的JVM优化方法,如死代码消除,代码嵌入以及循环体优化. Java最引以为豪的特性"平台独立性"正是源于Java编译器.软件开发人员尽其所能写出最好的java应用程序,紧接着后台运行的编译器产生高效的基于目标平台的可执行代

随机推荐