Java虚拟机

jVM内存结构

在这里插入图片描述
程序计数器:线程私有,主要保存下一条指令的地址
方法区:保存装载的类信息,以及常量池,字段方法信息,通常和永久区关联在一起。
堆内存:线程共享加堆,存放对象实体(垃圾回收的主要区域
java虚拟机栈:线程私有,由栈帧组成,当线程调用一个方法时,栈帧入栈,用于保存该方法的局部变量表,动态连接,方法出口等。【一直递归下去,则可能会出现stackOverFlowError,则需要动态扩展,如果扩展到无法申请足够的内存空间,则会出现OOM】.
**本地方法栈:**线程私有,和java虚拟机栈类似,只不过是由C++、C等语言编写的。

垃圾回收

主要是对堆内存进行回收,

如何判断一个对象可被回收

  1. 引用计数法:当对象增加一个引用时计数器加一,当引用计数为0时,可被回收,【当循环引用时,则无法被回收】
  2. 可达性分析算法:以GC Roots为起始点进行搜索,如果对象可达,则是存活的,如果不可达,则被回收。
    GC Roots包含:
    1) 虚拟机栈中局部变量表所引用的对象;
    2)本地方法栈中所引用的对象;
    3)方法区中类静态属性所引用的对象;
    4)方法区中的常量所引用的对象;

引用类型

强引用:new 一个对象的形式,不会被回收,即使内存不足,也会抛出OOM异常,但是不会被回收;
软引用:在内存不足时被回收,通常用于内存敏感的高速缓存;

Object obj = new Object();
SoftReference<Object> sf = new SoftReference<Object>(obj);
obj = null;  // 使对象只被软引用关联

弱引用:在进行垃圾回收时一定被回收;用于缓存

Object obj = new Object();
WeakReference<Object> wf = new WeakReference<Object>(obj);
obj = null;

虚引用:随时都可能被回收,甚至不能通过get方法来获取,设置虚引用的唯一目的是当这个对象被回收时能收到一个系统通知。

Object obj = new Object();
PhantomReference<Object> pf = new PhantomReference<Object>(obj, null);
obj = null;

垃圾回收算法

1。标记清除算法:为每个对象进行检查,如果是活动对象,则进行标记,在清除阶段对其进行清除。
缺点:会产生大量碎片化内存,
2。标记整理算法:让所有存活对象向一端移动,然后清除边界以外的内存;
缺点:虽然不会产生碎片化,但是会需要移动大量对象
3。复制算法:将内存分为两部分,适用于只有少量存活的情况。
缺点:只使用一半内存
4。分代收集:老年代适用于标记整理或者标记清除算法,新生代适用于复制算法;

垃圾收集器

在这里插入图片描述

内存分配和回收策略

内存分配策略:
执行 Minor GC

  1. 对象先分配在Eden区,当Eden区空间不足时,发起Minor GC;
  2. 在Minor GC存货的对象会移动到Survicor中,年龄增加一岁,
  3. 如果对象太大,或者长期存活,则会直接移到老年代;
    执行 Full GC
  4. 调用System.gc()只是建议虚拟机执行,不一定会真正去执行;
  5. 老年代空间不足,
  6. 使用复制算法的Minor GC需要老年代的内存空间进行担保,如果担保失败则会执行full GC;

java对象模型

组成:
对象头:锁状态标志、线程持有的锁等标志
实例对象
填充对象

java中new一个对象的过程

1)为自己的实例变量和从父类继承过来的实例变量进行内存分配;,同时赋默认值
2) 进行变量赋值,主要包括:实例变量初始化,实例代码块初始化,构造函数初始化。

new一个对象的执行过程
1)加载父类:为父类静态属性分配空间并赋予初值,执行父类静态初始代码块
2)加载自类:为子类静态属性分配空间并赋予初值,执行子类静态初始代码块
3)加载父类构造器:为父类非静态属性赋予初值,执行父类非静态代码块,执行父类构造函数。
4)加载子类构造器:为子类非静态属性赋予初值,执行子类非静态代码块,执行子类构造函数。
总的来说,类的实例化过程:父类的类构造器() -> 子类的类构造器() -> 父类的成员变量和实例代码块 -> 父类的构造函数 -> 子类的成员变量和实例代码块 -> 子类的构造函数。

类的加载过程

一个java文件在编译之后会生成一个或多个class文件,(若一个类中含有内部类,则编译后会生成多个class文件)
加载:通过一个类的全名获取此类的二进制字节流,将这个字节流的静态存储结构转换为方法区的运行时数据结构,在内存中生成这个类的Class对象,作为方法区这个类的各种数据的访问入口。【类加载机制----------双亲委培机制------类加载器】
连接:分为准备,验证,解析
1)验证:确保所加载的Class文件中所包含的信息符合当前虚拟机的要求。
2)准备:为类变量分配内存并进行初始化,【在方法区中进行分配】。
3)解析:将常量池中的符号引用替换为直接引用的过程,主要针对类或接口,字段,类方法。等符号引用。
初始化:开始执行java代码,初始化是执行**类构造器(与实例构造器不同)**的过程。【类构造器是由编译器自动收集类中的所有类变量的赋值动作和静态代码块并产生,执行顺序与出现顺序相同】、
**补充知识:**类构造器只能被初始化一次,如果多个线程,则只有一个线程初始化,其余线程阻塞。

类加载器

  1. 启动类加载器:使用C++实现,是虚拟机的一部分; <JRE_HOME>\lib 目录下的,无法被java程序直接引用,如果要将加载请求委派给启动类加载器,直接使用null即可;
  2. 扩展类加载器: <JAVA_HOME>/lib/ext 或者被 java.ext.dir 系统变量所指定路径中的所有类库加载到内存中,开发者可以直接使用扩展类加载器
  3. 应用程序类加载器:由于这个类加载器是 ClassLoader 中的 getSystemClassLoader() 方法的返回值,因此一般称为系统类加载器。它负责加载用户类路径(ClassPath)上所指定的类库,开发者可以直接使用这个类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器

双亲委派机制

在这里插入图片描述

一个类加载器首先将类加载请求委托给父类加载器,只有当父类加载器无法完成时才会尝试自己加载;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值