JVM详情

JVM详情

一、JVM内存划分

  1. 堆:存放new出来的对象;(成员变量)

  2. 方法区:存放的是类对象;(静态变量)

  3. 栈(虚拟机栈, 本地方法栈):存放方法之间的调用关系;(局部变量)

  4. 程序计数器:存放的是下一个要执行的指令;

注意:变量存放在哪一个区域,和变量类型无关!和变量的形态(局部,成员,静态)有关!

  • a 是成员变量,在堆上
  • b 是静态变量,在方法区
  • c 是成员变量,在堆上
  • d 是静态引用对象在方法区,new 出来的对象在堆上
  • A 是局部变量,在栈上,new 出来的对象在堆上

二、双亲委派模型(重点考察)

什么是双亲委派模型?

    一个类加载器收到类加载请求,首先自己不会加载这个类,而是把这个请求委派给父类加载器完成,每一层都是如此,因此所有加载请求最终都会送到最顶层的加载器中,只有父加载器反馈无法加载这个请求,子类才会尝试去加载;

2.4.2、涉及到的类加载器

  1. Bootstrap ClassLoader :负责加载标准库中的类;

  2. Extension ClassLoader:负责加载JVM扩展的库的类(标准库中没有,但JVM自己实现出了);

  3. Application ClassLoader :负责加载我们自己的项目中的自定义类;

三、 GC(垃圾回收机制)

 在学习C语言的过程中,需要通过 malloc 申请内存,最后通过 free 进行释放,这里就容易存在一个问题------忘记free,造成内存泄漏;而GC(垃圾回收)就是一个主流处理方案;

垃圾的判定算法

  • 可达性分析(JVM采用)

     顾名思义,就可以到达的变量
     约定一些特定的变量,成为 "GC roots", 每隔一段时间,从 GCroots 出发,进行遍历,查询哪些变量是能够被访问到的,能被访问到的变量就称为 "可达",否则就是 "不可达"
     
     -- 栈上的变量;
    
     -- 常量池引用的对象;
    
     -- 方法区中静态属性引用对象;
    
     -- 方法区中常量引用的对象;
    
  • 引用计数

     每多一个引用指向该对象,计数器就+1;
     每少一个引用指向该对象,计数器就-1;
     当计数器的数值为 0 时,就说明这个对象已经没有人能够再使用了,此时就可以进行释放;
     但是如果有相互引用的情况,类似于死锁,那这个内存就永远也释放不了
    

垃圾回收算法

  • 标记-清除算法

     简单来说,就是标记出垃圾后,直接把对象对应的内存空间进行释放;
     
     但是假如释放了3块空间不连续,那么虽然内存上有3块空间,但是却new不出一个完整的2块空间
     
     引起了内存碎片问题
    
  • 复制算法

    这是针对内存碎片问题,引入的办法;

        具体的,将内存分成两块大小相等的空间,但只使用其中的一块,当需要进行垃圾回收时,就把正在使用的那块空间上还存活的对象复制到另一块上,再将使用过的那块内存全部清空;这样做的好处就是不用再考虑内存碎片问题;
     1. 空间利用率相比标记清除法更低了;
     2. 但是若一轮GC下来,大部分需要保留,只有极少数要回收,这时候复制的开销就很大了;
    
  • 标记整理算法

    标记过程与 "标记-清除算法"一致,但后续步骤不是直接对可回收对象进行清理,而是让所有存活对象都向一端连续性的覆盖,然后直接清除掉边界以外的空间;(类似于顺序表的删除元素)
    
  • 分代算法

    分代算法综合了上面所说的三种算法,通过区域划分,实现不同区域用不同的垃圾回收策略,从而实现更好的垃圾回收
    
     1. 刚创建出来的对象,进入伊甸区;
    
     2. 若新对象熬过一轮GC,没被回收,就通过复制算法,复制到生存区;
    
     3. 生存区的对象也要经历GC,每熬过一次GC,就会通过复制算法拷贝到另一个生存区(只要这个对象不死亡,就会在两个生存区来回拷贝);
    
     4. 如果一个对象在生存区中,反复坚持了很多轮还没去世,就会被放到老年代(老年代GC的频率会降低);
    
     5. 若对象来到了老年代,也会进行定期的GC,只是频率更低了;老年代采取标记整理的方式来处理垃圾;
    
相关推荐
何曾参静谧几秒前
「C/C++」C/C++ 之 变量作用域详解
c语言·开发语言·c++
程序媛小果7 分钟前
基于java+SpringBoot+Vue的宠物咖啡馆平台设计与实现
java·vue.js·spring boot
追风林12 分钟前
mac m1 docker本地部署canal 监听mysql的binglog日志
java·docker·mac
芒果披萨27 分钟前
El表达式和JSTL
java·el
q5673152327 分钟前
在 Bash 中获取 Python 模块变量列
开发语言·python·bash
许野平1 小时前
Rust: 利用 chrono 库实现日期和字符串互相转换
开发语言·后端·rust·字符串·转换·日期·chrono
也无晴也无风雨1 小时前
在JS中, 0 == [0] 吗
开发语言·javascript
狂奔solar1 小时前
yelp数据集上识别潜在的热门商家
开发语言·python
duration~1 小时前
Maven随笔
java·maven
zmgst1 小时前
canal1.1.7使用canal-adapter进行mysql同步数据
java·数据库·mysql