整理一些最近学习到有关Java语言的一些计算机底层知识,能更好的理解Java这门语言,JVM中一些设计流程跟计算机底层设计的原理有很相似的地方,虽然程序员不应该受语言的限制,但总要先从一门语言入手,学到语言的一些设计理念,感觉这些都是相通的。

1、机器语言

在计算机的世界里面只存在0和1,通过0和1的各种组合,来让机器认识这些数字组合并进行运算。机器是如何识别出来这些数字的呢,计算机实际上就相当于一个巨大的电路,在这个电路中存在许许多多的开关,01就代表了这些开关的状态,那无数的开关就可以组成各种组合,与门、或门、非门、异或门等等,通过这些来进行数据的一个计算。

在这个基础上就延伸出来很多的学科,在硬件方面,有模电、数电、电路等,学过的人都知道这几门课程是如何的折磨你的逻辑思维。这些都是硬件的基础,学会它们之后才会进行下一步的学习,例如如何设计电路,如何在芯片上绘制这些电路,如何排线等等。

在这之中如何操纵这些开关就有了机器语言的出现,带实现机器的运行,但是机器语言都是有01组成的,对于人来说阅读和编写都很困难,所以有了汇编语言的出现,它其实是一种机器语言的助记符,来帮助程序员识别出来这个组合代表什么命令,能够快速一点,就像是眼睛看到苹果这个物体时,大脑马上反射出这个东西用语言描述为苹果。

2、解释型语言

什么叫解释型语言呢?就拿JAVA来说,它就属于解释型语言,java语句经过编译后形成字节码(bytecode)文件,这个文件计算机是识别不了的,通过jvm的解释后变为机器语言发送到cpu进行命令的执行,这样的方式就可以实现java的可移植性,只需要替换不同能够在对应系统能够运行的jvm就可以,无需改动java的代码。

与解释型语言相对的就编译型语言,例如C语言,编译之后直接能生成机器语言,在机器上运行,无需再经过解释器这一步骤。

3、计算机组成


Java中的底层原理 java底层原理怎么学_java

此图来源于http://mashibing.com

CPU是整个计算机的执行命令的模块,所有命令的执行都在这里进行。如下图所示就是CPU的简单模型,里面包含了很多个模块。

PC -> Program Counter 程序计数器 (记录当前指令地址)

Registers -> 暂时存储CPU计算需要用到的数据

ALU -> Arithmetic & Logic Unit 运算单元

CU -> Control Unit 控制单元

MMU -> Memory Management Unit 内存管理单元

cache->CPU的缓存单元

现代的CPU都用超线程的功能,是指单个CPU里面有一个ALU对应多个Registers和PC的组合,这样就可以把多个线程的上下文信息存到CPU之中,这样就减少了频繁上下文切换的问题,减少性能的损耗。

CPU的缓存为三级缓存L1、L2、L3,L1、L2这两级缓存属于每个CPU独有的,L3属于多核共享的,这个就很Mybatis中的一级、二级缓存异曲同工。这三级缓存的访问速度是一次降低的,访问L1的速度是最快的。

读取数据是直接把硬盘数据按块读取的内存中,能够提高读取的效率,从内存中读取速度要比在硬盘中读取的速度快很多。

在CPU读取数据的过程中,因为L1、L2是CPU核内独享的,所以当有多个CPU读取到同一个缓存行,那就会造成数据同步的问题,这时候就产生一个MESI Cache内存一致性协议(inter),还可以进行锁总线的操作。是当一个CPU核修改了这缓存行的数据,这时候就会通知另一CPU核这条数据已经失效,需要再从内存中读取。在inter里,缓存行一行为64字节。

上述的情况会出现伪共享的情况,这时候可以使用缓存行对齐的方式,在数据前放7个long,中间放数据,后面再放7个long,这样cursor就会单独占据一个缓存行,就不会出现伪共享问题。

在java中也有缓存行对齐的实现,jdk1.7使用的就是上述方法long padding,jdk1.8后提供了@Contended注解,启动时需要加上-xx:RestrictContented参数

当java中,new一个新对象时,是先向内存中申请内存空间,之后调用构造是才回会把数值存入到内存中。

CPU的乱序执行的特点是为了提高效率,但有一些的程序是需要顺序执行的,所以出现了内存屏障来禁止乱序执行,通过读锁、写锁、读写锁、总线锁,JVM也存在了内存屏障,通过写锁、读锁,在命令前后同时加上屏障,组成了4个屏障类型,jVM规定的重排序有8条原则,叫happen-before。还有一个词叫as if serial指的是单线程执行结果不变,看上去像是顺序执行。

UMA结构是多个CPU共享一个内存,统一内存访问空间,这样就会造成性能降低,所以后续出现了NUMA,CPU会优先访问离自己最近的插槽内存,以提高性能。