本文改编自[我是一个 Java class](hhttps://mp.weixin.qq.com/s?__biz=MzAxOTc0NzExNg==&mid=416976590&idx=1&sn=22823ada76d8cfd26a43e8d3a7b7a60e&scene=21#wechat_redirect)
## Classloader
javac把java代码变成了class文件,可以通过的文件开头的几个数来确定的是否是java的类以及是由jdk的哪个版本编译出来的
那么如何找到class文件呢?
* 在环境变量里面设置的路径找
* 如果使用Eclipse编译,可能会多三级,比如com/mytaobao/domain
* 如果找不到,会抛出ClassNotFound异常。
假设这个class文件的全名叫 com.mytaobao.domain.Account
## classLoader的分级
为什么的classLoader分级呢?
因为之前有个黑客类写了java.lang.String,与String的名字一模一样,但是里面竟然有格式化硬盘的代码。
为了预防这种风险,可以将ClassLoader分层,像String,ArrayList等只能由最顶层的Bootstrap,Extension等Classloader来加载,如果加载不了,再问AppClassloader
而文件验证器的主要作用是对class中的字节码进行检查分析,确保每个指令是正确的,检查是不是有超类,是不是覆盖了final方法,跳转指令是否正确。
## 虚拟机
class会被加载到内存中的方法区,然后new一个新的Account对象,编号是"Account@659e0bfd"
这个对象会被放到堆里面。
当CPU开始调用某个线程的时候,会开始调用class,因为线程会按照class的机器码进行执行
![](http://p8a6vmhkm.bkt.clouddn.com/picgo20180811144205.png?picgo)
![](http://p8a6vmhkm.bkt.clouddn.com/picgo20180811144224.png?picgo)
使用栈的原因在于简单。
只需要入栈和出栈就行了,不像intel的CPU中的桶,每个桶只能容纳一个数(寄存器),做加法的时候,需要把数放到不同的桶里面,然后加起来的结果还得放到新桶里面。
线程有不止一个工作台, 而是一摞子工作台, 也是一个压一个, 线程们都很老实,永远在最上面那个工作, 从来不会先干下面的活。
这些工作台也是栈,学名叫 Java 栈,每个线程都有一个, 其中的每个工作台你看过了 ,学名叫栈帧, 每个台子都代表一个方法调用, 这一摞工作台就方法调用方法导致的啊
一旦调用新方法, 立刻就会形成一个新的工作台, 压在老的上面。 方法调用完成后, 栈顶的工作台就被销毁了, 线程会在底下的工作台继续机械的干活。
## 堆
清理者:专门清理没有用的对象,比如说Account@659e0bfd,他可能是一个局部变量,方法结束后就没人引用了,如果不清理就会住满,out of memory
那么可以多分配些空间给堆吗?这是由程序员决定的,在启动虚拟机的时候会指定参数。
那么清理者如何知道对象是否有人用?可以看引用计数。
如果对象被使用, 计数就会增加, 不用的时候就会减少, 如果是 0 , 那就可能被清理。