Java基础2:JVM学习总结
来源:互联网 发布:yy会员签到软件 编辑:程序博客网 时间:2024/05/01 21:26
JVM内存分哪几个区,每个区的作用是什么?
PC寄存器是用于存储每个线程下一步将执行的JVM指令地址,如该方法为native的,则PC寄存器中不存储任何信息。
第二块:栈(Stack)
JVM栈是线程私有的,每个线程创建的同时都会创建JVM栈。
JVM栈是用来存储当前线程中局部变量表(Java中定义的八种基本类型:boolean、char、byte、short、int、long、float、double)、方法返回结果(还有方法返回地址)以及StackFrame,对于基本数据类型的变量,则直接存储它的值;对于引用类型的变量,则存的是指向对象的引用。
栈是以帧为单位保存当前线程的运行状态,每当线程调用一个Java方法时,JVM就会在该线程对应的栈中压入一个帧,这个帧自然就成了当前方法使用的当前帧。栈帧由三部分组成:局部变量区、操作数栈、帧数据区。当执行这个方法时,它使用这个帧来存储对应方法的局部数据:参数、局部变量、中间运算结果等等。方法执行完,对应的帧则从栈中弹出,并把返回结果存储在调用方法的帧的操作数栈。
JVM栈上的所有数据都是私有的。任何线程都不能访问另一个线程的栈数据,所以我们不用考虑多线程情况下栈数据访问同步的情况。
第三块:堆(Heap)
JVM堆是JVM中所有线程共享的,因此在其上进行对象内存的分配均需要进行加锁,这也导致new对象的开销比较大。
JVM堆是用来存储对象实例以及数组值的区域,可以认为Java中所有通过new创建的对象的内存都在此分配,Heap中的对象的内存需要等待GC进行回收。
①有时候也成为永久代,在该区内很少发生垃圾回收,但是并不代表不发生GC,在这里进行的GC主要是对方法区里的常量池和对类型的卸载
②方法区主要用来存储已被虚拟机加载的类的信息、常量、静态变量和即时编译器编译后的代码等数据。
③该区域是被线程共享的。
④方法区里有一个运行时常量池(Runtime Constant Pool),用于存放静态编译产生的字面量和符号引用。其中字面量比较接近Java语言层面的常量概念,比如文本字符串,声明为final的常量值等。该常量池具有动态性,也就是说常量并不一定是编译时确定,运行时生成的常量也会存在这个常量池中。
第五块:本地方法堆栈(Native Method Stacks)
JVM采用本地方法堆栈来支持native方法的执行,此区域用于存储每个native方法调用的状态。
五、JVM垃圾回收机制
(1)对新生代的对象的收集称为minor GC;
(2)对旧生代的对象的收集称为Full GC;
(3)程序中主动调用System.gc()强制执行的GC为Full/Main GC。
2、垃圾回收器常用的算法
GC(Garbage Collectio)为了能够正确释放对象,会监控每一个对象的运行状态,包括对象的申请、引用、被引用、赋值等,GC都需要进行监控。监视对象状态是为了更加准确地、及时地释放对象,而释放对象的根本原则就是该对象不再被引用。
- ①标记-清除(Mark-Sweep)
- 这是垃圾收集算法中最基础的,根据名字就可以知道,它的思想就是标记哪些要被回收的对象,然后统一回收。这种方法很简单,但是会有两个主要问题:1.效率不高,标记和清除的效率都很低;2.会产生大量不连续的内存碎片,导致以后程序在分配较大的对象时,由于没有充足的连续内存而提前触发一次GC动作。
- ②复制算法(Copying)
- 为了解决效率问题,复制算法将可用内存按容量划分为相等的两部分,然后每次只使用其中的一块,当一块内存用完时,就将还存活的对象复制到第二块内存上,然后一次性清楚完第一块内存,再将第二块上的对象复制到第一块。但是这种方式,内存的代价太高,每次基本上都要浪费一般的内存。
于是将该算法进行了改进,内存区域不再是按照1:1去划分,而是将内存划分为8:1:1三部分,较大那份内存交Eden区,其余是两块较小的内存区叫Survior区。每次都会优先使用Eden区,若Eden区满,就将对象复制到第二块内存区上,然后清除Eden区,如果此时存活的对象太多,以至于Survivor不够时,会将这些对象通过分配担保机制复制到老年代中。(java堆又分为新生代和老年代) - ③引用计数法 (Reference Counting)
- 引用计数器在微软的 COM 组件技术中、Adobe 的 ActionScript3 种都有使用。引用计数器的实现很简单,对于一个对象 A,只要有任何一个对象引用了 A,则 A 的引用计数器就加 1,当引用失效时,引用计数器就减 1。只要对象 A 的引用计数器的值为 0,则对象 A 就不可能再被使用
- ④标记-压缩算法 (Mark-Compact):标记-压缩算法是一种老年代的回收算法,它在标记-清除算法的基础上做了一些优化。也首先需要从根节点开始对所有可达对象做一次标记,但之后,它并不简单地清理未标记的对象,而是将所有的存活对象压缩到内存的一端。之后,清理边界外所有的空间。这种方法既避免了碎片的产生,又不需要两块相同的内存空间,因此,其性价比比较高。
⑤分代收集(Generational Collecting):现在的虚拟机垃圾收集大多采用这种方式,它根据对象的生存周期,将堆分为新生代和老年代。在新生代中,由于对象生存期短,每次回收都会有大量对象死去,那么这时就采用复制算法。老年代里的对象存活率较高,没有额外的空间进行分配担保,所以可以使用标记-整理 或者 标记-清除。
- Java基础2:JVM学习总结
- 【Java基础】JVM学习
- Java基础学习总结(119)——Java8 JVM与Java7 JVM比较
- Java基础学习总结(111)——Java虚拟机JVM总结大全
- Java基础之JVM内容总结
- Java基础学习总结(121)——Java JVM执行流程
- Java基础学习总结---------异常Exception(3) -JVM默认如何处理异常
- Java基础学习总结(120)——JVM 参数使用详细说明
- Java基础学习总结
- java基础学习总结
- Java基础学习总结
- java基础--学习总结
- JAVA学习总结之JVM概述
- 7. java基础学习总结2
- Java基础学习总结---------异常Exception(2)
- 学习总结2(java基础)
- jvm学习之jvm基础
- Java基础学习总结(96)——Java虚拟机JVM及Tomcat中的JVM有关内存的设置与调优
- RTB 广告投放流程详解
- iOS平台下闪退原因汇总(一):"Ran out of trampolines of type 0/1/2" 运行时间错误
- 类型转换函数 & 转换构造函数
- Groovy中对xml的操作补充
- laravel5.5 常用 artisan 命令
- Java基础2:JVM学习总结
- Linux字符设备驱动框架
- 进度条
- POJ 2653 Pick-up sticks(线段规范相交)
- 20170907
- oracle替换掉字段中存在的特殊符号以及空格
- 491. Increasing Subsequences
- Koa学习1
- NIO使用实例