通过操作系统来了解JVM(企图找到操作系统和JVM间千丝万缕的关系)

文章目录

  • Java跨凭台原理
  • 进程和线程的区别
  • 进程的通信方式和线程的同步方式
    • 进程的通信方式
    • 线程同步方式

我学完操作系统后,发现里面很多都是理论性的知识,然后我是学Java开发的,所以进过我查询资料,写了这篇文章,企图将操作系统里的理论值知识和Java语言世界建立起联系。 大家在看我的文章时如果发现我有哪里说的不对,非常欢迎大家给我指正,小菜鸟的我非常惶恐。。
我直接先抛出我的结论,我从历史上来说先有的操作系统,在有的JVM,所以感觉JVM很多实现方式都是参考操作系统的实现方式。

  • 我们想要了解操作系统和Java或者说JVM之间的联系,我们先从Java为何能说自己是具有一次编译,到处运行的特点!

Java跨凭台原理

我是一名软件工程的学生,学习过学校操作系统课程过后,因为我主攻的方向是Java Web开发。我们知道Java的跨凭台特性是因为它和C系列语言不同,Java语言并不与操作系统直接进行交互。需要解释成字节码文件然后由基于不同操作系统的JVM来解释成当前操作系统能够的对应平台的机器码。

  • Java能跨平台原理
    通过操作系统来了解JVM(企图找到操作系统和JVM间千丝万缕的关系)_第1张图片
  • Java和C/C++语言相比
    通过操作系统来了解JVM(企图找到操作系统和JVM间千丝万缕的关系)_第2张图片
    Java源程序(.java)要先编译成与平台无关的字节码文件(.class),然后字节码文件再解释成机器码运行。解释是通过Java虚拟机来执行的。

字节码文件不面向任何具体平台,只面向虚拟机。

Java虚拟机是可运行Java字节码文件的虚拟计算机。不同平台的虚拟机是不同的,但它们都提供了相同的接口。

Java语言具有一次编译,到处运行的特点。就是说编译后的.class可以跨平台运行,前提是该平台具有相应的Java虚拟机。但是性能比C/C++要低。

Java的跨平台原理决定了其性能没有C/C++高

  • 什么是JVM?什么是JDK? 什么是JRE?
  1. JVM :JVM是Java Virtual Machine(Java虚拟机)的缩写,它是整个java实现跨平台的最核心的部分,所有的java程序会首先被编译为.class的类文件,这种类文件可以在虚拟机上执行,也就是说class并不直接与机器的操作系统相对应,而是经过虚拟机间接与操作系统交互,由虚拟机将程序解释给本地系统执行。JVM是Java平台的基础,和实际的机器一样,它也有自己的指令集,并且在运行时操作不同的内存区域。 JVM通过抽象操作系统和CPU结构,提供了一种与平台无关的代码执行方法,即与特殊的实现方法、主机硬件、主机操作系统无关。JVM的主要工作是解释自己的指令集(即字节码)到CPU的指令集或对应的系统调用,保护用户免被恶意程序骚扰。 JVM对上层的Java源文件是不关心的,它关注的只是由源文件生成的类文件(.class文件)。

  2. JRE:JRE是java runtime environment(java运行环境)的缩写。光有JVM还不能让class文件执行,因为在解释class的时候JVM需要调用解释所需要的类库lib。在JDK的安装目录里你可以找到jre目录,里面有两个文件夹bin和lib,在这里可以认为bin里的就是jvm,lib中则是jvm工作所需要的类库,而jvm和lib和起来就称为jre。所以,在你写完java程序编译成.class之后,你可以把这个.class文件和jre一起打包发给朋友,这样你的朋友就可以运行你写程序了(jre里有运行.class的java.exe)。JRE是Sun公司发布的一个更大的系统,它里面就有一个JVM。JRE就与具体的CPU结构和操作系统有关,是运行Java程序必不可少的(除非用其他一些编译环境编译成.exe可执行文件……),JRE的地位就象一台PC机一样,我们写好的Win32应用程序需要操作系统帮我们运行,同样的,我们编写的Java程序也必须要JRE才能运行。

  3. JDK:JDK是java development kit(java开发工具包)的缩写。每个学java的人都会先在机器上装一个JDK,那 让我们看一下JDK的安装目录。在目录下面有六个文件夹、一个src类库源码压缩包、和其他几个声明文件。其中,真正在运行java时起作用的是以下四个文件夹:bin、include、lib、jre。现在我们可以看出这样一个关系,JDK包含JRE,而JRE包含JVM。

bin:最主要的是编译器(javac.exe)

include:java和JVM交互用的头文件

lib:类库

jre:java运行环境

  • 通过这一节我可以这么理解其实JVM相当于一个Java语言的操作系统,帮助我们运行我们的Java代码。

进程和线程的区别

  • 当我们了解Java跨屏太原理后,那我们就对JVM有了一个了解,那么在我们学习操作系统的时候更多的提到的是进程的概念,可是在我们Java中用到的都是多线程,而对进程不是那么多的提到,这并不是代表进程和我们没有一点关系。我先说我的结论最早操作系统是没有线程概念,只有进程,但是进程的操作太过于重量级,进程上下文切换动不动就要切换到内核态,这时就有了线程,所以我们线程是为了简化进程的操作而做的创新。下面我们来具体说说进程和线程区别,通过它来看看操作系统和JVM的区别。

  • 进程:一个在内存中运行的应用程序。每个进程都有自己独立的一块内存空间,一个进程可以有多个线程,比如在Windows系统中,一个运行的xx.exe就是一个进程。

  • 线程:进程中的一个执行任务(控制单元),负责当前进程中程序的执行。一个进程至少有一个线程,一个进程可以运行多个线程,多个线程可共享数据。与进程不同的是同类的多个线程共享进程的堆和方法区资源,但每个线程有自己的程序计数器、虚拟机栈和本地方法栈,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程。

  • 从上面我们可以知道进程和线程的几点不同:

  1. 根本区别:进程是操作系统资源分配的基本单位,而线程是处理器任务调度和执行的基本单位
  2. 资源开销:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同
  3. 类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。
  4. 包含关系:如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。
  5. 内存分配:同一进程的线程共享本进程的地址空间和资源,而进程之间的地址空间和资源是相互独立的
  6. 影响关系:一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程都死掉。所以多进程要比多线程健壮。
  7. 执行过程:每个独立的进程有程序运行的入口、顺序执行序列和程序出口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制,两者均可并发执行
  • 多进程和多线程区别
    多进程:操作系统中同时运行的多个程序
    多线程:在同一个进程中同时运行的多个任务

  • 总结:
    JVM是一份本地化的程序,本质上是可执行的文件,是静态的概念。程序运行起来成为进程,是动态的概念。
    java程序是跑在JVM上的,严格来讲,是跑在JVM实例上的,一个JVM实例其实就是JVM跑起来的进程,二者合起来称之为一个JAVA进程。各个JVM实例之间是相互隔离的。所以,我们能够知道,我们的每个Java程序运行于JVM整体是一个JVM实例,它是一个进程,而在这个JVM实例里为了更高效的在进程分配的有限的时间片里能够更加运行,这个时候我们通过进程下的多线程来管理进程资源,多个线程共享进程的资源。这个时候就有了JVM的内存模型,内存模型规定了线程的运作方式,而操作系统规范了进程的运作。
    当我们在操作系统层面一般讨论是进程,而在JVM层面一般讨论的是多个线程的高效运行。

进程的通信方式和线程的同步方式

  • 这一节我们通过进程的通信方式和线程的同步方式来聊聊操作系统和JVM的关系。在很多博客里面写的是多线程的通信方式,这个说法,我感觉并不能说是错,我感觉不太准确。因为在前面一节我们知道进程是操做系统层面,因为多进程间因为资源分配不一样,这才导致了他们需要进行通信,比如说通过共享内存的方式进行通信。但是当我们站在多线程的角度去看待这个问题时就不一样了,因为多个线程共享进程的资源,你这个通过共享内存的方式去进行通信讲不通呀!但是我当时就想,那我们JVM不是也有多个线程共享的区域,方法法区和堆,我们可以用方法区来当共享内存来实现线程通信或者说是同步!当然这个想法瞬间胎死腹中,因为JMM,我们JVM为了线程的高效运行有了JMM机制。但是这样来说那么操作系统中学到的进程的通信方式,对于我们线程来说就一点用都没有了吗?当然不是,我们前面就说过,先有的进程,才有的线程,这样那么我们线程之间的交流方式肯定是基于进程进行改进。例如Java中的CAS操作,虽然具体实现方法不同,但是CAS的思路和共享内存的进程通信方式相同呀!这样我们就可以知道,在我们考虑线程的同步方式时候,虽然不可以直接将进程的通信方式直接套用,但是考虑线程同步时我们可以以进程的同步方式来作为基础去思考我们的线程的同步方式。

进程的通信方式

通过操作系统来了解JVM(企图找到操作系统和JVM间千丝万缕的关系)_第3张图片

  • 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
  • 命名管道 (named pipe/FIFO) : 命名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
  • 信号量( semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
  • 消息队列( message queue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
  • 信号 ( sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
  • 共享内存( shared memory ) :共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。
  • 套接字( socket ) : 套解字也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同设备间的进程通信。

线程同步方式

  • 锁机制:包括互斥锁、条件变量、读写锁(锁机制就和我们进程通信方式里的信号量机制相同,从我们Java所得具体实现原理也可以看到信号量思想的体现)
  1. 互斥锁提供了以排他方式防止数据结构被并发修改的方法。
  2. 读写锁允许多个线程同时读共享数据,而对写操作是互斥的。
  3. 条件变量可以以原子的方式阻塞进程,直到某个特定条件为真为止。对条件的测试是在互斥锁的保护下进行的。条件变量始终与互斥锁一起使用。
  • 信号量机制(Semaphore):包括无名线程信号量和命名线程信号量
  • 信号机制(Signal):类似进程间的信号处理(在进程通信中有信号概念,当然在我们线程同步中也有,例如interupt方法)

只有进程间需要通信,同一进程的线程share地址空间,没有通信的必要,但要做好同步/互斥mutex,保护共享的全局变量。而进程间通信无论是信号,管道pipe还是共享内存都是由操作系统保证的,是系统调用。

具体Java中多线程同步机制大家可以看我的另外一篇博客Java中线程同步的七种实现方式

你可能感兴趣的:(#,JVM,操作系统)