JVM和传统OS对比

前言

在linux中,可执行文件没有唯一的后缀名,本文以”可执行文件”统称

jvm体系的class文件对应于linux中的可执行文件,jvm对应于linux os,两者有很多相象的地方。但毕竟机理不同,class文件和可执行文件的不同正是两个os机理不同的反映。

而本质上的不同,则要追溯到java的起源:面向网络,为了让“可执行文件”在网络上传输并在不同的系统上执行,发散出很多机制。

本文以jvm为“主场”,以传统os为“客场”,在讲述jvm的过程中,对比jvm与传统os的不同。

jvm

学习jvm主要有以下几大块

  1. class文件格式
  2. class文件加载
  3. jvm内存模型(内存回收)

    由java区域和native区域组成,每个区域分为堆栈两个部分。java区域中,还有一个永久代,存储共享的,生命周期基本上跟java进程一样的数据。(永久代在有的jvm实现产品中没有)

  4. jvm对象模型

  5. jvm解释器(字节码指令执行)

类似于《程序员的自我修养》的书在阐述传统os时,并没有“内存模型”之类的术语(只会讲述通过分段和分页来管理内存的基本原理)。我们总是以传统os的眼光来审视jvm这个虚拟的os,反过来讲,以jvm(几大块的组成)来看待传统可执行文件的文件格式、加载和执行过程,也是非常有意义的。

内存模型和解释器

java是一种跨平台的编程语言,为了跨平台,jvm抽象出了一套内存模型和基于栈的解释器,进而创建一套在该模型基础上运行的字节码指令。(这也是本文不像其它书籍一样先从”class文件格式”讲起的原因)

  1. 为了跨平台,不能假定平台特性,因此抽象出一个新的层次来屏蔽平台特性,因此推出了基于栈的解释器,与以往基于寄存器的cpu执行有所区别。

  2. 字节码指令 = 操作码 + 操作数,(操作数可以是立即数,可以存在栈中,也可以是指向堆的引用(引用存在栈中)) 传统的指令 = 操作码 + 操作数,(操作数据可以是立即数,可以存在寄存器中,也可以是指向内存的引用)此处jvm的栈,说的是栈帧,跟传统的栈还是有不同的,粗略的讲,我们可以说在jvm体系中,用栈替代了原来寄存器的功能。

    这句话的不准确在于,对于传统cpu执行,线程之间共用的寄存器,只不过在线程切换时,借助了pcb(进程控制块或线程控制块,存储在线程数据所在内存页中),pcb保存了现场环境,比如寄存器数据。轮到某个线程执行时,恢复现场环境,为寄存器赋上pcb对应的值,cpu按照pc指向的指令的执行。

    而在jvm体系中,每个线程的栈空间是私有的,栈一直在内存中(无论其对应的线程是否正在执行),轮到某个线程执行时,线程对应的栈(确切的说是栈顶的栈帧)成为“当前栈”(无需重新初始化),执行pc指向的方法区中的指令。

  3. 类似的编译优化策略

    同一段代码,编译器可以给出不同的字节码(最后执行效果是一样的),还可以在此基础上进行优化。比如,对于传统os,将内存中的变量缓存到寄存器。对于jvm,将堆中对象的某个实例属性缓存到线程对应的栈。而c语言和java语言是通过共享内存,而不是共享寄存器或线程的私有栈来进行线程“交流”的,因此就会带来线程安全问题。因此,c语言和java语言都有volatile关键字。(虽然这不能完全解决线程安全问题)

堆的管理

其实跟内存的碎片管理是一样的。可执行文件的加载因为程序大小的不一致,导致内存分配的碎片化。对象的加载,因为对象大小的不同,导致堆的碎片化。

双方有些共同点

  1. 都不按实际的大小分,可执行文件会占用整数个页,对象占用的空间则会补齐(整字长倍)。
  2. 在内存中都有“热门”和“冷门”的区别,有的对象(或可执行文件)经常被调用,有些用过即不用了。因此大家想了不同的办法解决,传统os选择“向外扩展”,把暂时不用的扔到硬盘上。jvm选择对内区别对待,堆区域分代。
  3. 程序和可执行文件 本身,都将“方法之类”的数据共享,“数据之类”的数据保存多份。

class文件格式以及class文件的加载因平时应用较少,暂不过多涉及

class文件格式

因为指令中包含了操作数,可执行文件不只是指令的堆砌。

操作数大部分是地址引用,寄存器(或栈)成了存储引用的地方,作为cpu和内存的“中转站”。还有一些符号引用,需要在指令之前,描述这些符号引用。

class文件中包含方法和属性信息,这些数据为反射机制提供的基础。

class文件的加载

加载的本质,从磁盘上加载,得到的是一个字节数组,然后按照自己的内存模型,把字节数组中对应的数据放到对应的地方。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值