首页 > 其他分享 >JVM

JVM

时间:2022-10-04 22:33:30浏览次数:36  
标签:初始化 对象 线程 JVM 方法 加载

是什么

Java Virtual Machine 翻译为Java虚拟机

为什么

  • 提供了JAVA程序的运行环境,保证了JAVA运行与平台无关的特性

  • 定义了JVM规范,保证了JAVA代码的统一性和规范性

  • JVM在运行期间提供了内存分配和垃圾回收的作用

工作流程

类加载

加载

先通过类的全类名获取到类的二进制文件,封装二进制文件到运行时常量池,再在堆中创建Class对象,用于封装运行时常量池中的数据结构,并对外提供访问接口

类加载器

分类

  • 启动类加载器

    主要加载核心类,例如以java.开头的jar包

  • 扩展类加载器

    主要用于加载具有扩展功能的jar包

  • 应用程序类加载器

    主要用于加载ClassPath目录下的jar包

  • 自定义类加载

机制

  • 双亲委派机制

    是什么?

    • 在请求类加载时,类加载器接收到请求,并不会直接进行加载,而是会先将这个请求传递给父类加载器,一直传递到启动类加载器,再由启动类加载器判断能否加载该类,若是不行,则将请求原路向下传递,直到碰到了可以加载的类加载器为止

    为什么?

    • 防止一个JVM中出现多个同类名相等的类的情况

      • 问题:同一JVM中可以存在俩个String类吗?

        不行,因为存在双亲委派机制,每次类加载的时候会先由启动类加载器加载,而String属于核心类,即使String类多次加载,每一次到启动类加载器,都会被判断加载过,不会再次加载

  • 破坏双亲委派机制

    是什么?

    双亲委派问题:例如,DriverManager类在使用时需要使用到Driver类,而DriverManager类是由启动类加载器加载的,而Driver实现类是由应用程序类加载器加载的,所以DriverManager无法直接调用Driver实现类

    解决:为了解决类似的问题,Java虚拟机提出使用线程上下文类加载器,例如当DriverManager类需要调用Driver实现类时,就使用线程上下文类加载器来获取Driver实现类,这样就是破坏双亲委派机制

    为什么?

    双亲委派机制缺点:子类加载器加载的类可以访问父类加载器加载的类,但是父类加载器加载的类是无法访问子类加载器加载的类

    原因:双亲委派机制和类加载器的命名空间

连接

  • 验证

    验证Class对象是否符合规范

  • 准备

    为静态变量分配内存

  • 解析

    将符号引用解析为直接引用

初始化

可以说,初始化阶段是执行类构造器 < clinit > 方法的过程。首先说下类构造器 < clinit > 方法和实例构造器 < init > 方法有什么区别。< clinit > 方法是在类加载的初始化阶段执行,是对静态变量、静态代码块进行的初始化。而< init > 方法是new一个对象,即调用类的 constructor方法时才会执行,是对非静态变量进行的初始化

类被加载之后并不会立刻进行初始化,只有当类首次被主动引用时才会进行初始化

主动引用

  • 使用new创建对象
  • 使用反射创建对象
  • 调用类属性/类方法
  • JVM启动类

被动引用

  • 定义对象数组
  • 调用类常量

引申:对象加载

对象创建过程

  • 先判断对象对应的类是否被加载,需要先进行类加载

  • 内存分配

  • 初始化默认值

  • 设置对象头

    对象头中包含了是否充当锁,HashCode值,GC年龄等

  • 执行初始化方法(init方法)

对象初始化过程

  • 初始化父类中的静态成员变量和静态代码块
  • 初始化子类中的静态成员变量和静态代码块
    • 以上这俩个步骤执行于类加载阶段
  • 初始化父类的普通成员变量和代码块,再执行父类的构造方法
  • 初始化子类的普通成员变量和代码块,再执行子类的构造方法
    • 以上这俩个步骤执行性于对象创建过程

JVM运行时结构

线程共享

  • 堆主要用于存储对象,数组

  • 堆中包含新生代,老年代和eden区,占用内存比例为8:1:1

    新对象会在新生代,大对象和长期存活的对象会存储在老年代

方法区

  • 在JDK7中,方法区的具体实现是永久代

    在JDK8中,方法区的具体实现为元空间,元空间会直接占用计算机内存,但是在逻辑上属于JVM

  • 方法区中包含了常量池,字符串常量池被迁移到了堆中,但是运行时常量池仍然在方法区

线程私有

栈空间中有栈帧,每次调用方法都会使用栈帧封装方法的主要信息,包含方法名,参数,局部变量等等,方法执行完毕,进行出栈

程序计数器

程序计数器主要用于存储计算机下一个指令的地址

垃圾回收

垃圾回收算法

新生代

复制算法

老年代

  • 标记清除法
  • 标记整理法

垃圾回收器

串行

GC单线程内存回收, 暂停所有用户线程

并行

多个线程进行GC, 暂停所有的用户线程

  • JDK8默认使用并行垃圾回收器

    • 缺点:造成STW

    • 优点:内存占用小,数据吞吐量大

并发

用户线程和GC线程同时执行(不一定是并行, 可能是交替执行), 不需要停顿用户线程(停顿时间很短)

  • CMS
  • G1

调优

调优就是找平衡点

调优目的

  • 让老年代的对象尽可能少

  • 让GC次数减少,时间减少

  • 解决内存泄漏

调优步骤

  • 监控JVM状态
  • 分析结果
  • 进行调整
  • 重复监控

调优方案

  • 减少创建对象的数量
  • 减少使用全局变量和大对象 ( 很可能会进入老年代 )
  • 调整新生代和老年代的大小到最合适
  • 选择合适的GC收集器

标签:初始化,对象,线程,JVM,方法,加载
From: https://www.cnblogs.com/qhlb/p/16754670.html

相关文章

  • java的jvm堆中的内存泄露和内存溢出的概念以及区别【杭州多测师】【杭州多测师_王sir
    一、什么是内存溢出和内存泄露内存泄漏(memoryleak):是指程序在申请内存后,无法释放已申请的内存空间,导致系统无法及时回收内存并且分配给其他进程使用。通常少次数的内存无......
  • 浅谈JVM模型以及Class文件是怎么被加载的
    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档@目录前言一.什么是JVM二、JVM类加载机制1.类加载的概念2.类加载具体流程3.类加载器4.双亲委派机制4.1......
  • jvm 自带调优工具一览
    jdk在安装的时候会提供一些性能分析、故障诊断、JVM监控之类的工具,了解这些工具对我们分析JVM内存、JVM调优有一定的帮助,本篇文章来学习一下。监控类工具jpsjps(JVMProcess......
  • 主线程异常会导致 JVM 退出?
     大家好,我是坤哥上周​​线程崩溃为什么不会导致JVM崩溃​​在其他平台发出后,有一位小伙伴留言说有个地方不严谨他认为如果JVM中的主线程异常没有被捕获,JVM还是会崩溃......
  • 002 JVM的类加载机制—— JVM的类加载阶段——双亲委派机制
    1.10.1JVM的类加载阶段JVM的类加载分为5个阶段:加载、验证、准备、解析、初始化。在类初始化完成后可以使用该类的信息,在一个类不再被需要时可以从JVM中卸载。1.10.3......
  • JVM 运行时内存 -01
    JVM运行时内存Survivor([səˈvaɪvə®]----Eden[ˈiːdn]-----MinorGC[ˈmaɪnə®]少数的;轻微的;较小的;次要的MajorGC[ˈmeɪdʒə®]GC专业;少校;主修课程;专......
  • 学习笔记(一) netty jvm参数配置命令
    命令值范围说明备注io.netty.leakDetectionLevelDISABLED-完成禁止检测内存泄漏,这个是不推荐。SIMPLE-如果buffer中出现1%的内存泄漏,打印错误日志,就是上......
  • jvm虚拟机内存管理的简单介绍
    jvm内存分为虚拟机栈,堆,方法区,程序计数器,本地方法栈 jvm分为五大模块,类装载器子系统,运行时数据区,执行引擎,本地方法接口,垃圾收集模块JVM运行时内存 JDK7的内存结构......
  • JVM内存溢出问题排查
    内存溢出outofmemory:通俗理解就是内存不够用了,是我们工作当中经常会遇到的问题,内存溢出有可能发生在正常的情况下,而非代码层面问题导致,比如高并发下,大量的请求占用内......
  • JVM调优
      下面是跟可大算法  打击清除的三种算法:   Mark-Sweep标记法缺点:内存碎片化,--这样就装不下大的对象了;   Copying算法--一分为二  ......