栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【JVM】

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【JVM】

JVM
  • JVM内存区域划分
    • 程序计数器
    • 栈
    • 堆
    • 方法区
  • JVM类加载
  • 双亲委派模型
  • 垃圾回收相关
  • 垃圾回收器


JVM内存区域划分 程序计数器

内存中最小的区域,保存了下一条要执行的指令的地址在哪

栈

存放局部变量和方法调用信息。每个线程有一个

堆

程序中创建的所以对象都保存在堆中。
一个进程只有一个,多个线程共用一个堆。内存中空间最大的区域

局部变量在栈上
成员变量和new的对象在堆上

方法区

用来存储被虚拟机加载的类信息,常量,静态变量,即编译器编译后的代码等数据的。

JVM类加载

类加载其实是设计一个运行时环境的一个重要的核心的功能
类加载是把.class文件加载到内存中,构建成类对象。
类加载过程:

(一)加载(Loading)
先找到对应的.class文件,然后打开文件并读取.class文件,同时初步生成一个类对象
(二)连接(Linking)
建立好多个实体之间的联系
(1)验证(Verification):验证读到的内容是否和规范中规定的格式完全匹配,如果发现读到的数据格式不符合规范,就会类加载失败,并且抛出异常
(2)准备(Preparation):给静态变量分配内存,并且设置上类变量初始值
(3)解析(Resolution):Java虚拟机将常量池内的符号引用替换为直接引用的过程,也就是初始化常量的过程。
(三)初始化(Initialization)
初始化阶段就是执行类构造方法的过程

class A{
    public A(){
        System.out.println("A的构造方法");
    }
    {
        System.out.println("A的构造代码块");
    }
    static {
        System.out.println("A的静态代码块");
    }
}
class B extends A{
    public B(){
        System.out.println("B的构造方法");
    }
    {
        System.out.println("B的构造代码块");
    }
    static {
        System.out.println("B的静态代码块");
    }
}
public class test07 extends B{
    public static void main(String[] args) {
        new test07() ;
        new test07();
    }
}

执行结果:
A的静态代码块
B的静态代码块
A的构造代码块
A的构造方法
B的构造代码块
B的构造方法
A的构造代码块
A的构造方法
B的构造代码块
B的构造方法
注:
(1)类加载阶段会进行静态代码的执行,要想创建实例,必须先进行类加载;
(2)静态代码块只是类加载阶段执行一次
(3)构造方法和构造代码块,每次实例化都会执行,构造代码块在构造方法前面
(4)父类执行在前,子类执行在后

双亲委派模型

双亲委派模型,描述的是JVM中的类加载器,如何根据类的全限定名(java.lang .String)找到.class文件的过程。

如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一层次的类加载器都是如此,因此所有的加载请求最终都应该传送到最顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求时,子加载器才会尝试自己去完成加载。

  • 默认的类加载器:
    (1)BootStrapClassLoader:负责加载标准库中的类
    (2)ExtensionClassLoader:负责加载JDK扩展的类
    (3)ApplicationClassLoader:负责加载当前项目目录中的类

  • 双亲委派模型优点:
    (1)避免重复加载类
    (2)安全性

垃圾回收相关
  • 垃圾回收的劣势:
    (1)消耗额外的开销
    (2)可能会影响程序的流畅运行

垃圾回收要回收的:
(1)程序计数器。固定大小,不涉及到释放,也就不需要GC
(2)栈。函数执行完毕,对应的栈帧就自动释放了,也不需要GC、
(3)堆。代码中大量的内存都在堆上,需要GC
(4)方法区。类对象,类加载来的。进行类卸载就需要释放内存

  • 如何判定垃圾:
    (1)基于引用计数
    引用计数简单可靠高效但是有缺陷:1)空间利用率低 ;2)会有循环引用的问题
    (2)基于可达性分析
    通过额外的线程定期的针对整个内存空间的对象进行扫描。有一些起始位置会类似于深度优先遍历一样,把可以访问到的对象都标记一遍(带有标记的对象就是可达的对象),没被标记的对象就是不可达,也就是垃圾
  • 回收垃圾三种基本策略:
    (1)标记-清除
    (2)复制算法。为了解决内存碎片(直接释放,内存还给了系统,但是被释放的内存是离散的,带来的问题就是内存碎片)

复制算法的问题:
(1)内存空间利用率低
(2)如果要保留的对象多,要释放的对象少,此时复制开销就很大

(3)标记-整理
针对复制算法进行改造

垃圾回收器

(1)串行收集有Serial收集器,Serial Old收集器等
(2)并发收集有ParNew收集器,Parallel Old收集器,Parallel Scavenge收集器等

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1013633.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号