将java文件转换成.class文件,JVM将.class文件放在机器上能运行00011上运行 write once on everywhere
真的是一次编译,到处运行吗???
例如:windows和linux,其实他们的jar或者war包是一样的,但是环境所安装的jdk版本是不一样的,说到底还是定制化的。
理解这句话的意思还是很微妙的
JVM的两个方面是至关重要的
(1)机器码翻译,将我们认识的指令到机器认识的指令间的转换
(2)内存管理
JVM所涉及java方面的内容就是运行时数据区,这个甚至比内存管理还要重要
类被类加载加载。。验证。。解析后,把东西分别放到运行时数据区。然后类的功能就是分别去运行时数据区里取数据,指令。
bu
大类是数据和指令
程序计数器:指向正在执行的线程的指令地址//也可以理解为指令计数器
它不单要指向还要记录
为什么要记录?
线程是在cpu里执行的,cpu是用时间片来执行的,而时间片是抢占式的,也就是说线程为什么是分时间段执行的,
一个线程可能不一定执行完就去执行另一个线程,所以,指令运行到哪,当然需要记录了,这时候就需要用到程序计数器。
虚拟机栈:存储线程运行方法时所需的数据,指令和
注意是方法,运行时数据区包含了类的所有东西,而虚拟机栈则只存方法的相关东西,但有一个地方是例外的,就是常量池,还存了类的一些东西还有全局变量等,下面有讲。
虚拟机栈里有很多的栈帧组成,每个栈帧有什么组成呢,见图
虚拟机栈是每个线程独享的
如果一个方法里面比较单一,就往虚拟机栈里压一个栈帧,如果方法里面调其它方法,则会压多个栈帧
虚拟机栈存局部变量表,八大基本类型和引用类型的地址,地址指向的是堆里面的对象,局部变量表是32位的,也就说地址也最多是32位
动态链接其实就是常量池,常量池不单单存常量,还有字段,类全限定名,方法等描述的东西也存在常量池里
当.do()方法用到的时候,需要获取service接口的实例,而这个实例存放在常量池里面
出口:方法运行结束的时候,需要出栈;正常情况是return,还有异常的情况,
两个方法互相循环调用,栈里有几个栈帧??TODO
本地方法栈是没有实现类,是有c和c++写的,此处不讨论
方法区:类信息,常量(1.7)静态变量,JIT(just in time)
类信息是指类的元信息,介绍类有什么东西
这里存的常量和常量池里面的常量好像有相同的地方???TODO
哪些是线程独享和共享的。
堆:--->>>得先讲内存模型JMM
首先上来肯定是子孙三代:新生代,老年代,永久代(1.8之前)
观察上面的两张图的颜色可以看出,三代分别在哪?新生代,老年代在堆,永久代在方法区,1.8之后永久代是存放在堆外内存
8:1:1 差不多2/8原则
新生代中的s1放不下了放在老年代
GC算法有很多种,
引用计数法不行,因为a->b b->a就没法回收
GCRoot进行可达性分析来判断,
不可达一会被回收吗?不一定,可以用finalize()来挽救变成可达,但是实用性不强