class文件通过类加载器进生成Class模板(元空间,即方法区的实现),然后根据模板创建对象(堆当中),栈只是用来指向堆当中的对象。
java堆和方法区是jvm公有部分,数据共享的,也是GC的作用域
执行引擎:解释代码并交给jvm运行
pc寄存器:每个线程私有,存储每个线程下一行要执行的行号(行号指示器),pc寄存器是通过字节码解释器而被改变的
本地方法栈:本地方法都加载到这里
本地方法库:调用底层C语言的一些方法
本地方法接口:调用本地方法的接口
本地方法栈 调用 本地方法接口 将 本地方法库中的方法加载到本地栈中
一个对象从创建到被回收的过程:
一个对象被创建时存储在堆当中的新生区(GC作用域的三分之一,字符串常量池也放在堆中)中的伊甸园区(新生区的十分之八),当伊甸园区满的时候开始一波轻GC,存活对象放在幸存0区,存活对象年龄加1,然后当伊甸园区满的时候再次进行轻GC,此次进行GC处理的不止伊甸区还有幸存区中的from区,存活对象统一放在幸存区中的to区,所有对象年龄加1,当有对象年龄到达15时,被放到养老区(整个存储的三分之二),养老区满的时候会发生一次重GC,速度是轻GC的十分之一,如果养老区赶不上新产生对象的速度,就会内存溢出,jvm挂机。如果对象内存过大则会直接进入养老区。
如何判断是不是垃圾?
1.引用计数法,对每个对象进行计数,但是没办法解决循环引用的问题(两个对象中属性相互指引,堆中内存一直被占用)
2.跟可达:到达GCRoots之间有引用链,可作为GCroots的有,方法区中的静态变量,方法区中的引用对象,栈中的引用对象。
怎么进行GC?
1.复制算法:新生区采用,将幸存者移至to区,年龄加1,到达15移至养老区(To区内存一直为空,浪费内存空间);需要要求对象存活率低
2.标记清除:老年区采用,将需要被回收的对象进行标记,然后停止应用进行清除(会产生内存碎片,影响用户体验)
3.标记压缩:老年去采用,将存活对象进行标记,然后没有被标记的被回收,然后根据内存地址将存活对象进行压缩整理,JVM只需要持有一个内存的起始地址即可,这比维护一个空闲列表显然少了许多开销。(效率太慢)
类是如何被加载到内存当中的?
使用到的是双亲委派模型,类加载器在收到加载请求之后,首先不会自己加载,而是请求委托给父类,依次向上,直至启动类加载器进行加载,自上而下,如果启动类加载器无法加载,就请求给子类拓展类加载器进行加载,应用类加载器,用户自定义加载器分别进行加载,如果可以加载则返回,如果不能加载则报ClassNotFoundException。
类在被加载到内存中,而后进行的连接和初始化
连接又分为三步:
1.验证:验证字节码是否正确
2.准备:为类的静态变量分配空间并赋予初始值
3.解析:加载此类所需要的其他类
初始化:为类的变量赋予真正的值
使用
卸载