一:运行时数据区
1.这当中线程 共享和线程私有:
01.线程共享:
堆, 方法区
02.线程私有
虚拟机栈,本地方法栈,程序计数器
程序计数器:
在计算机操作系统中程序计数器表示这个程序要执行的下一个指令的地址,对于JVM中的程序计数器可以看做是当前线程所执行的字节码的
行号指示器,每个线程都有一个程序计数器(当线程都在执行的时候,如果线程要切换将要保证线程回归到正确的位置),重要的一点——
程序计数器,这是JVM规范中唯一一个没有规定会导致
OutOfMemory(内存泄露,下文简称OOM)的区域。
虚拟机栈:
基本数据类型的变量和对象的引用变量都存在此区域;
遵循“
先进后出,
后进先出”的原则;
这块区域可能会抛出StackOverflowError或者OOM错误。设置JVM参数”-Xss228k”(栈大小为228k)。
StackOverflowError:
线程请求的栈深度大于了虚拟机规定的最大深度;
OutOfMemoryError:
虚拟机在扩展栈时,无法申请到足够的内存空间,
本地方法栈:
在Hotspot中
虚拟机栈和本地方法栈合为一体,
堆:
所有对象的实力和数组开辟的空间都在此区域保存;
所有线程共享;
GC主要回收对象的区域;
堆分区:
新生代
老年代
永久代
方法区:(静态区)
所有线程共享;
方法(包含构造函数),接口 定义在此区域;
所有方法的信息;
存放静态变量+常量+类信息+方法信息+常量池;
常量池中存放程序在编译期间生成的各种变量以及符号引用
二:生命周期
类的生命周期从类被加载,连接和初始化开始
到类的卸载结束
01.类的生命周期中,类的的2进制数据位于方法区
02.在堆区会有一个描述的Class对象
类的加载: 需要类加载器
将Class字节码文件内容加载到内存中,并将这些静态数据转化成法区中运行时数据结构!
在堆中生成一个Class对象;这个Class对象就是方法区类数据的访问入ロ
类的连接:
验证: 在编译期间
类结构检查
语义检查 语法检查
字节码验证 确保jvm认识
准备
为static修饰的赋初始值
类的解析
将符号引用转变成直接引用
初始化
加载不是初始化 初始化指的是实例化!
创建出类的实例初始化的时机
1. 类的主动引用
new—个类的对象
通过反射的 newinstance()
再初始化子类的时候必须先初始化父类
2. 类的被动引用
通过类名访问静态的内容
调用类的静态常量也不会初始化类
用类作为对象数组存在时,也不会初始化类
子类调用父类的静态变量不会加载子类的静态代码块(不会执行类的准备
类被主动引用的时候会被初始化
在被动引用的时候不会
三:垃圾回收机制(GC)
3.1:为什么需要垃圾回收机制
01.只要是对象被创建,那么就会在虚拟机的堆中开辟空间;
02.程序运行过程中会创建N个对象,每个对象都会有自己的空间;
03.如果每个对象都永久占用这块内存空间,显然内存是不够的;
为了保证其他的对象能够被正确的创建;
在C语言中,垃圾回收机制的任务是程序员自身负责;
可能出现的问题:
01.由于程序员大意,导致没有及时释放不适应的对象,释放错误;
02.程序员一旦释放程序核心的对象,可能会导致系统崩溃;
3.2:垃圾回收机制的定义
在java程序运行过程中,jvm中有一个专门负责回收那些不在使用的对象所占用的内存;
这种回收的过程,我们称之为垃圾回收机制(GC);
3.3:垃圾回收机制的特点
01.减轻了程序员进行内存管理的负担;
02.防止系统内存被非法释放,是我们的程序更加健壮;
03.只有在对象不被任何变量引用的时候,才会被回收;
04.程序无法强制让垃圾回收机制立即回收垃圾操作;
05.当垃圾回收器要回收不用对象的内存时会先调用这个对象的finalize()
这个方法有可能回事对象复活,导致垃圾回收机制取消对该对象的回收。
3.4 :对象的状态
在java虚拟机的垃圾回收器来看,堆中所有的对象都有3种状态!
01.可触及状态
02.可复活状态
03.不可触及状态
只有对象处于不可触及状态的时候,垃圾回收期才会真正的释放对象所占有的内存!
1.对象的生命周期开始( new语句或者是反射中newInstance ) 可触及状态
2.对象不在被引用,或者对象调用了finalize() 可复活状态
3.对象调用了finalize() 不可触及状态
4.垃圾回收
5对象的生 命周期结束
3.5 :垃圾何时被回收(触发GC的条件)
01.对象没有引用===》对象处于不可触及状态
02.程序在作用域正常执行完毕之后
03. System. exit()
04.程序以外终止
3.6 :详解GC
01.什么时间=== )触发GC的条件
001. System. gc( )可能触发;
002.系统自身决定GC的触发时机
根据Eden区和From Space区的内存大小来决定!
02.对什么东西
java中的对象=== )通过分析算法无法找到的对象
03.做了什么
对搜索到的对象进行复制操作;
对搜索不到的对象执行finalize()。
如果真正的回收一个对象,要至少需要两次标记!
01.第一次标记:对于一个没有其他对象引用的时候;执行finalize()
02.第次标记:针对于筛选过的对象, 进行回收。
3.7 : java中内存分配机制
核心:分代分配,分代回收!
新生代(Young Generation)
Eden 区 :是连续的内存空间,所以分配内存极快
Survivor区 :From To必须有一个区域是空的
老年代(old Generation)
永久代(Permanet Generation)
注意点:
01.绝大多数创建的对象被分配在Eden区,但是大多数对象会在这个区域死亡!
02.当Eden区满的时候,会执行Minor GC,将死亡的对象清理掉
3.7 : java中内存分配机制
核心:分代分配,分代回收!
新生代(Young Generation)
Eden 区 :是连续的内存空间,所以分配内存极快Survivor区 From To必须有一个区域是空的=
老年代(old Generation)
永久代(Permanet Generation) ===》方法区
回收两种数据:
01.常量池中的常量
02.无用的类信息
什么时候回收?
01.类所有的实例都被回收了
02.加载类的ClassLoader也被回收了03.类对应的Class对象没有被引用
注意点:
01.绝大多数创建的对象被分配在Eden区,但是大多数对象会在这个区域死亡!
02.当Eden区满的时候,会执行Minor GC(Young GC) ,将死亡的对象清理掉,
剩余存活的对象存放到survivore区(survivor1区必然为空)
03.以后每次Eden区满的时候,会执行Minor GC,所有存活的对象又被放进survivor0区
04.当survivor0区满的时候,会把存活的对象复制到survivor1区,之后清空survivore区!
05.反复执行之后,仍然活着的对象复制到老年代!
06.老年代的内存比年轻代要大,但是也有满的时候,当老年代满的时候执行Major GC(Fu1l GC)
07.如果对象比较大,年轻代存放不下,就会直接把对象放进老年代!
Young GC和Fu11 GC的区别:
01. Young GC是在新生代的Eden区满,Survivor区 满的时候触发
Full GC是在老年代满的时候触发
02. Young GC执行的频率高
Full GC执行的频率低
什么时候触发Full GC
01.执行System. gc(),系统建议执行Full GC,但不是必须执行
02.老年代空间不足
001.当Young GC执行后存活的对象需要进驻老年代,但是发现老年代空间不足
002.当Survivore区,Survivor1区来回切换时,发现内存不足,必须放进老年代,而且老年代空间不足
03.方法区空间不足
3.8:GC涉及到的算法
01.引用计数法 Refernce Counting
给对象增加一个引用计数器,使用一次引用+1,少一个引用-1;
当引用为0的时候回收;
但是不能解决循环引用的问题;
02.根搜索算法
对象以根作为起点,向下延伸,延伸的路径我们称为 引用链
当一个对象没有任何引用链链接的时候,证明这个对象是不可用对象(不可达),会被回收;
什么是根?
01.方法区中常量引用的对象
02.栈中引用的对象
03.静态属性引用的对象
03.复制算法Copying
就是将原有的内存空间分为两块,每次只能使用其中一块!
缺点就是浪费一半的内存空间!比标记清除算法要高效!
不适合存活对象较多的区域使用!在新生代使用!
04.标记清除算法Mark -Sweep
001把所有存活的对象打个标记
002 .把所有没有标记的对象统一清除
缺点:
01.两个过程效率都慢,因为需要想查询
02.因为在清除过程中会产生内存碎片,如果有大对象将无法存储
04.标记一整理算法Mark Compact
适合存活对象多的区域,所以适合在老年代使用!
总结没有了,看到这行留个言,,