本来这次应该讲讲ORM的几个框架,但是笔者还没有完全总结出来,所以这里先插入一次学习JVM的心得。作为一个Java程序员,如果不了解JVM的工作原理,就很难从底层去把握Java语言和Java程序的运作机制。这里先推荐一个最权威的讲解JVM的文档,大家只要查过Java API的可以在里面的一个叫“API, Language, and Virtual Machine Document”的标题下看到四个子标题,第一个是我们最熟悉的Java API Specification,很少会有人注意到第三和第四个子标题,分别是“The Java Language Specification”和“The Java Machine Specification”后面都带有(Download)字样,JVM的那个URL直接链接到http://java.sun.com/docs /books/vmspec/2nd-edition/这里地址。我们可以下载到一份非常权威详细的讲解JVM原理的官方文档。笔者业余时间花了1个星期来阅读,这里把自己的收获跟大家来分享一下,大概从这么几个方面来谈一谈:
1. JVM的实现机制
Java虚拟机就是一个小的计算机,有自己的指令集,有自己的文件系统,管理内部的表和数据,负责读取class文件里面字节码,然后转换成不同操作系统的CPU指令,从而使得Java程序在不同的操作系统上顺利的跑起来。所以Window的JVM能把字节码转换成Window系统的指令集,Linux的 JVM能把字节码转换成Linux系统的字节,同理还有Solaris,它们彼此之间是不能通用的。最早一款的原型虽然是Sun公司开发的,但发展到现在其实任何厂商都可以自己去实现一个虚拟机,用来读取字节码转换成OS指令。甚至我们可以认为JVM跟Java编程语言都没有关系,因为你自己哪怕用记事本写一串字节码,也可以让JVM来解析运行,只要你的字节码能通过JVM的验证。
JVM的验证其实是很严格的,这里只讲一些有趣的地方。大家还记得Java的图标是一个杯咖啡麽?究其历史我们也许可以查出为什么,但还有更显而易见的方式是JVM怎么判断一个文件是否是class文件?JVM的做法是读取前4个字节转换成16进制数,判断是否等于0xCAFEBABE这个数。注意到这个单词了麽?“cafebabe”,代表着国外一种咖啡品牌,似乎叫做Peet’s coffee-baristas之类。创造Java的人为了方便记忆,选择了这样一个16进制数作为标准class文件的头,所以任何class文件都必须具有这4个字节的头部。我们可以用DataInput这个接口的实现类来验证一下,读取任何一个class文件的第一个int,int在Java里面是四个字节。转换成16进制一定会是0xcafebabe的。
所以这里想告诉大家的是,JVM其实并没有那么神秘,我们完全可以理解它的构造。
2. Java相关的基础概念
配合JVM的结构,在Java语言中也会有很多特点比较鲜明的地方。比如对数值计算从来不会检查位溢出。任何变量存储的二进制即使位全部为1了仍然可以加,全部为0了仍然可以减。大家只要稍微测试一下就知道了,看这几个例子:
int max = Integer.MAX_VALUE;
int min = Integer.MIN_VALUE;
max+1 == min; //true
min-1 == max; //true
0.0/0.0 //得到“NaN”(Not a number)
1/0.0 //Infinity
-1/0.0 //-Infinity
1或-1/0 //ArithmeticException唯一的异常情况
看完这几个例子,大家是否能更好的把握Java的数值运算呢?Java完全遵照IEEE-754的标准来定义单双精度浮点数以及其他的数值存储方式。
另外Java里面有一个概念叫做Daemon Thread(守护线程),知道它的存在主要是为了理解虚拟机的生命周期。当我们运行java命令,从main函数进入的那一刻起,虚拟机就开始启动运行了。Main所在的主线程也会启动起来,它属于非守护线程。与之同时一些守护线程也会同时启动,最典型的守护线程代表就是GC(垃圾收集器)线程。JVM 虚拟机什么时候退出呢?是在所有的非守护线程结束的那一刻,JVM就exit。注意这个时候守护线程并未退出,很可能还要继续完成它的本职工作之后才会结束,但虚拟机的生命周期已经提前于它结束了。
3. JVM内部的基本概念
虚拟机内部还有一些概念,全部列举是不现实的,太繁琐也没有意义。除非您真的想自己去做一个JVM。笔者只列举部分概念:
首先我们来看一个叫做ReturnAddress的变量,它是JVM用来存储方法出口或者说进行跳转的依据,把任何地址存入这个变量就一定会按照这个地址来跳转。我们需要注意的就是finally有比方法return更高的赋值给ReturnAddress的优先级。同时存在方法return和 finally return的话,一定是按照finally里面的return为准。
JVM有自己的Heap,能被所有线程共享,存储着所有的对象,内存是动态被分配的。对于每个线程,拥有自己的Stack,栈里面存储的单位叫做 Frame(桢)。桢里面就记录着零时变量、对象引用地址、方法返回值等数据。JVM还有一个叫做Method Area的地方,存储着一段一段的可执行代码,每一段就是一个方法体,也能被所有线程共享。所以我们说一个线程其实从run方法跑起来,跟它的类中声明的其他方法是两个概念。因为其他的方法包括的所有的对象,这个时候都充当为资源被线程使用。
JVM有自己管理内存的方案,因为它具有文件系统的功能,我们可以看成一个小型的数据库,内部有许许多多不同的表。表的字段可能是另外一张表的地址,也可以直接就是一个存储数据值的地址值。JVM所有对运行时候类的解析验证计算等管理工作,实际上都是在管理这些表的变动,如果我们从数据库的角度来看,JVM所做的就是根据你的代码来操作那么多个表最后返回给你结果的过程。里面的表结构包括class的表、field表、method表、 attribute表等。
4. JVM的指令集
JVM有自己的指令集,笔者从前也看过一些计算机组成结构和汇编语言的数,建议大家也稍微看看,了解设计一个高效可用的计算机指令集是多么复杂又多么重要的过程。对于JVM的指令集,职责是管理好Java程序编译出来的字节码,相对而言指令集的名称就多少和Java语言相关了,比如指令集里就有 sastore,、saload表示array里面short的存和取、类似还有d2i表示从double转换成int、monitorenter表示进入synchronized块加锁、getstatic和putstatic表示对静态标量的存取、 jsr和ret等跳转指令……
为了便于记忆,设计JVM指令集的人们约定f开头的跟float有关,d跟double有关,i跟int有关,s跟short有关,a跟array有关。有兴趣的可以细读文档里面的每一个指令的作用。因为只是作为初步了解,这里就不多说了。
5. 一些Java关键字的实现原理
文档还很详细的列举了很多加载、初始化、加锁等操作的过程。笔者觉得比较有用的第一是记住Java里面只有Array不是由ClassLoader加载的对象,其他的对象全部都必须由一个ClassLoader来加载。另外package的概念除了类似于C++的namespace,是一种命名空间之外,底层的实现是规定同一个package下的类必须由同一个类加载器来加载,所以package的概念还可以认为是被同一个类加载器加载的类。
另外在多线程中,有很多细节值得去体会。每个线程有自己的Working memory,它们从能被共享的Main Memory中去读数据、修改、然后再存回去。笔者一直认为线程就是数据库里面事务的前身或者说祖先。我们只要稍微比较一下它们的行为,就会发现很多一致性。事务也是操作被事务共享的表数据,你改完我改,顺序不一致就会出现脏数据,而线程同样会出现脏数据。我们对线程加的锁策略,同样在事务中也有适用。当然多事务的情况显然比多线程更加复杂,但我们只要理解了多线程,相信对学习数据库事务的效果也是非常有帮助的。Java里面除了synchronized 能够帮助同步多线程之外,还有一个弱同步的操作关键字是volatile,它产生在变量上的约束在文档中也有详细的说明。因为很复杂,考虑到篇幅笔者就不打算解释一遍了。
好了,又是新的一篇结束了。大概再有一两篇笔者大学关于Java所学就差不多说完了。不足之处大家尽管提出来,笔者愿意接受各种职责批评,因为笔者认为失败的教训往往比成功更加助人成长。这个帖子一直以来得到那么多朋友的大力支持和鼓励,笔者在这里真诚的说一声谢谢!因为笔者即将毕业投入茫茫人海去从草根阶层开始挣扎,最近冷静的想了很多,即使毕业了,要提高的不止是技术,还包括很多综合素质,也许并不能马上找到如意的团队和工作岗位,只能承认自己是弱势群体,有时不得不向现实的生活低头,不知道今后是否还有这闲心去写学习笔记,去坚持走分享的道路。其实很多人我认为也很有心去分享,但被现实的生活束缚了手脚。所以也期望还呆在学校里的大学生们好好努力的珍惜那份无忧虑的心境和安静的环境,好好充实自己吧!
分享到:
相关推荐
Java学习杂谈系列涵盖了许多关于Java编程的基础概念和机制,以下是对这些知识点的详细解读: 1. **动态加载机制**: 动态加载机制是Java语言的一个关键特性,它使得程序在运行时才能确定哪些类需要加载。当你声明...
### Java学习杂谈:深入解析Java的动态加载机制、类搜索原理及JDK与JRE的区别 #### 动态加载机制解析 Java的学习者往往在掌握面向对象编程(OOP)概念时,会遇到“动态加载机制”这一关键点。相较于C++中面向过程...
### JAVA杂谈:深入探索Java的核心机制与实践 #### 动态加载机制解析 Java的动态加载机制是其面向对象编程(OOP)理念的核心体现之一,它使得Java能够在运行时根据需要加载类,而非在程序启动之初加载所有类。这种...
【Java动态加载机制】 Java的动态加载机制是其设计的一大亮点,它允许程序在运行时按需加载类,而不是一次性加载...在学习Java的过程中,实践和探索这些底层机制是非常有益的,能够提升我们的编程技巧和问题解决能力。
JRE(Java Runtime Environment)是运行Java程序所需的环境,包括JVM(Java Virtual Machine)和所有Java类库。JVM在Windows上通常表现为`jre/bin/client`目录下的`jvm.dll`文件。JDK(Java Development Kit)是用于...
第6节杂谈 [免费观看] 00:12:37分钟 | 第7节Java的发展历史00:27:24分钟 | 第8节Java的发展历史续00:02:27分钟 | 第9节Java技术体系00:08:46分钟 | 第10节jdk8的新特性00:07:31分钟 | 第11节lanmbda表达式简介...
JVM是Java知识体系中的重要部分,对JVM底层的了解是每一位Java程序员深入Java技术领域的重要因素。本课程试图通过简单易懂的方式,系统的深入讲解JVM相关知识。包括JVM执行过程、虚拟机类加载机制、运行时数据区、GC...
### Java杂谈:深入理解Java的关键概念 #### 动态加载机制:理解OOP思想的桥梁 Java作为一种纯粹的面向对象编程语言,其设计之初便致力于简化和优化面向对象编程(OOP)的概念,使之更加直观易懂。动态加载机制便是...
杂谈.mp4**:这个视频可能包含JVM领域的各种实用技巧、最佳实践和最新动态,比如JIT编译器的工作原理、JVM的并发优化、JVM与其他语言虚拟机的比较等。 5. **1.说在前面的话.mp4**:视频开头可能会介绍学习JVM的重要...
### Java杂谈——一个计算机专业学生几年的编程经验汇总谈 #### 一、关于动态加载机制 在Java中,动态加载机制是实现高效资源管理的关键之一。它允许Java虚拟机(JVM)根据需要加载类,而不是一次性加载所有的类。...
java8 集合源码分析 ...JVM Spring NIO DB及ORM 实用工具 设计模式 分布式 架构 算法 网络 Linux IDE JAVA 新版本 震惊,JAVA9已经不推荐使用 更震惊,预计9月份就要出JAVA11了 杂谈 正版电子书推荐
2. 创建的String对象数量:在JAVA中,字符串(String)是不可变的,当进行字符串的拼接或者创建新的字符串时,JVM会检查字符串池中是否存在相同的字符串,如果存在,则直接使用池中的对象,否则会在堆上创建新的对象...
“JAVA面试题解惑系列(六)——字符串(String)杂谈”可能涉及到String池的概念,即JVM会缓存重复的字符串,以提高性能。此外,String的equals()和==的区别也常常是面试的焦点,前者比较内容,后者比较对象引用。 ...
JDK是 Java 语言的软件开发工具包,主要用于移动设备、嵌入式设备上的java应用...JDK是整个java开发的核心,它包含了JAVA的运行环境(JVM+Java系统类库)和JAVA工具。本资源请先解压zip,解压后里面是tar.gz的linux压缩包