JVM总结2

1.基本概念

  • java代码执行

    • 代码编译class:javac
      • 源文件通过编译器产生字节码文件,
      • 字节码文件通过jvm的解释器编译成机器上的机器码
    • 装载class:ClassLoader
    • 执行class:
      • 解释执行
      • 编译执行
        • client compiler
        • server compiler
  • 内存管理

    • 内存空间
      • 方法区
      • 方法栈
      • 本地方法栈
      • pc寄存器
    • 内存分配
      • 堆上分配
      • TLAB分配
      • 栈上分配
    • 内存回收
      • 算法
        • copy
        • mark-sweep
        • mark-compact
      • sun jdk
        • 分代回收
          • 新生代可用的GC
            • 串行copying
            • 并行回收copying
            • 并行copying
          • Minor GC触发机制及日志格式
          • 旧生代可用的GC
            • 串行Mark -Sweep-compact
            • 并行compacting
            • 并发mark-sweep
          • Full GC触发机制以及日志格式
        • GC参数
        • G1
    • 内存状况分析
      • jconsole
      • visuaivm
      • jstat
      • jmap
      • mat
  • 线程资源同步和交互机制

    • 线程资源同步
      • 线程资源执行机制
      • 线程资源同步机制
        • Synchronized实现机制
        • lock/unlock的实现机制
    • 线程交互机制
      • Object.wait/notify/notifyAll-Double check pattem
      • 并发包提供的交互机制
        • semaphore
        • countdownLatch
    • 线程状态及分析方法
      • jstack
      • tda
        2.jvm内存
  • 线程私有

    • 程序计数器
      • 指向虚拟机字节码指令的位置
      • 唯一一个无oom的区域
    • 虚拟机栈
      • 虚拟机栈和线程的生命周期相同
      • 一个线程中,每调用一个方法创建一个栈帧
      • 栈帧
        • 本地变量表
        • 操作数栈
        • 对运行时常量池的引用
      • 异常
        • 线程请求的栈深度大于jvm所允许的深度StackOverflowError
        • 若JVM允许动态扩展,若无法申请到足够内存OutOfMemoryError
    • 本地方法栈
      • 异常
        • 线程请求的栈深度大于jvm所允许的深度StackOverflowError
        • 若jvm允许动态扩展,若无法申请到足够内存OutOfmemeryError
  • 线程共享

    • 方法区(永久代)
      • 运行时常量池
    • 类实例区(java堆-运行时数据区)
      • 创建的对象和数组都保存在java堆内存中,也是垃圾收集器进行垃圾收集的最重要的内存区域。
      • 新生代:eden;from survior;to survivor
      • 老生代
      • 异常
  • 直接内存

    • 不受jvm gc管理

3.jvm运行时内存

  • 新生代:占据堆的1/3空间,会频繁触发MinorGC进行垃圾回收
    • Eden区:java对象出生地,当Eden区不够会触发minorGC,对新生代进行一次垃圾回收
    • ServivorFrom:上一次GC的幸存者,作为这一次GC的被扫描者
    • ServivorTo:保留了一次MinorGC过程中的幸存者
    • MinorGC的过程(复制->清空->互换)
      • eden、servivorFrom复制到ServivorTo,年龄+1
      • 清空eden,servivorFrom
      • servivorTo和servivorFrom互换
  • 老年代
    • 存放应用程序中生命周期长的内存对象 。当无法找到足够大的连续空间分配给新创建的较大对象时也会提前触发一次 MajorGC 进行垃圾回收腾出空间。
    • MajorGC(标记清除算法):扫描一次所有老年代,标记存活对象,回收没有标记的对象,会产生内存碎片,为减少内存损耗,一般需要进行合成或者标记出来方便下次直接分配,当老年代也装不下了,抛出oom异常。
  • 永久代:内存的永久保存区域,存放Class和Meta(元数据)的信息。Class被加载时被放到永久区域,和存放实例区域不同,GC不会在主程序运行期对永久区域进行清理,导致永久代区域会随着加载class的增多而胀满,最终抛出oom异常
    • java8与元数据:元空间不在虚拟机中,而是使用本地内存,元空间大小受本地内存的限制,类的元数据放入native memory 字符串池和类的静态变量放入java堆中,这样可以加载多少类的元数据就不再由maxpermSize控制,而由实际可用空间来控制。

4.垃圾回收算法

  • 总结
    • gc
      • 哪些内存需要回收
      • 什么时候回收
      • 怎么回收
    • 哪些对象死亡
      • 引用计数法:循环引用的问题
      • 根搜索算法
        • GC roots:需要经过两次标记,两次标记后仍然是可回收对象,则将面临回收
        • Gc roots(可达性分析)
          • VM栈中的引用
          • 方法区中的静态引用
          • JNI中的引用
    • 垃圾收集算法
      • 标记清除:
        • 标记需回收对象,回收标记的
        • 效率低;内存碎片多
      • 复制:可用内存被压缩到了原本的一半
      • 标记整理:标记后存活对象移向内存一端,清除端边界外的对象
      • 分代收集:根据对象存活的不同生命周期将内存分为不同的域。
        • 新生代与复制算法:eden,from space,to space 8:1:1
        • 老年代和标记复制算法:每次只回收少量对象
    • 垃圾收集器
      • serial;parNew;parallel scavenge;serial old;parallel old;cms
    • 参数
      • Xms;Xmx;Xmn;-XX。。。

5.java四种引用类型

  • 强引用:把一个对象赋给一个引用变量,这个引用变量就是一个强引用。当一个对象被强引用变量引用时,它处于可达状态,它是不可能被垃圾回收机制回收的
  • 软引用:需要用 SoftReference 类来实现,对于只有软引用的对象来说,当系统内存足够时它不会被回收,当系统内存空间不足时它会被回收。软引用通常用在对内存敏感的程序中
  • 弱引用:需要用weakReference类实现,比软引用的生存期更短,对于只有弱引用的对象来说,只要垃圾回收机制一运行,不管jvm的内存空间是否足够,总会回收该对象占用的内存
  • 虚引用:需要用phantomRerence类来实现,不能单独使用,必须和引用队列联合使用,主要作用是跟踪对象被垃圾回收的状态。

6.垃圾收集器

  • Serial垃圾收集器(单线程,复制算法)
  • ParNew垃圾回收器:多线程复制算法,默认开启的cpu数目相同的线程数
  • Parallel scavenge收集器:多线程复制算法,高效。适用于在后台运算二不需要太多交互的任务。
  • Serial old收集器:单线程标记整理算法
    • 与新生代的parallel scavenge收集器搭配使用
    • 作为老年代中使用cms收集器的后备垃圾收集方案
  • parallel old收集器:多线程标记整理算法
  • cms收集器:多线程标记清除算法,主要目标是获取最短垃圾回收停顿时间,多线程清除算法。
    • 初始标记:标记和gc roots 直接关联对象,速度快。
    • 并发标记:进行gc roots 跟踪过程,和用户线程一起工作
    • 重新标记:修正并发标记期间,因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录
    • 并发清除:清除gc roots不可达对象,和用户线程一起工作。
  • G1收集器
    • 基于标记整理算法,不产生内存碎片
    • 精确控制停顿时间,不牺牲吞吐量前提下,实现低停顿垃圾回收。
    • 内存划分为大小固定的几个独立区域,并跟踪这些区域的垃圾收集进度
    • 每次根据所允许的收集时间,优先回收垃圾最多的区域,区域划分和优先级区域回收机制,确保G1收集器可以在有限时间获得最高的垃圾收集效率

7.Java IO/NIO

  • 阻塞IO模型:读写数据过程中会发生阻塞现象。
    • 用户线程发出 IO 请求之后,内核会去查看数据是否就绪,
      • 没有就绪就会等待数据就绪,而用户线程就会处于阻塞状态,用户线程交出 CPU。
      • 当数据就绪之后,内核会将数据拷贝到用户线程,并返回结果给用户线程,用户线程才解除 block 状态。
      • 典型的阻塞 IO 模型的例子为: data = socket.read();如果数据没有就绪,就会一直阻塞在 read 方法
  • 非阻塞IO模型:
    • 当用户线程发起一个 read 操作,不需要等待,马上就得到了一个结果。
      • 如果结果是一个error 时,数据还没有准备好,可以再次发送 read 操作。
      • 内核中的数据准备好了,并又再次收到了用户线程的请求,它马上就将数据拷贝到了用户线程,然后返回。
      • 非阻塞 IO 模型中,用户线程需要不断地询问内核数据是否就绪,非阻塞 IO不会交出 CPU,一直占用 CPU。
      • 问题: while 循环中需要不断地去询问内核数据是否就绪,这样会导致 CPU 占用率非常高,因此一般情况下很少使用 while 循环这种方式来读取数据。
  • 多路复用IO模型:
    • 有一个线程不断去轮询多个 socket 的状态,只有当 socket 真正有读写事件时,才真正调用实际的 IO 读写操作。
    • 通过 selector.select()去查询每个通道是否有到达事件,没有事件,则一直阻塞在那里,这种方式会导致用户线程的阻塞。只有当socket 真正有读写事件发生才会占用资源来进行实际的读写操作。
    • 多路复用 IO 比较适合连接数比较多的情况。
    • 注意:多路复用 IO 模型是通过轮询的方式来检测是否有事件到达,并且对到达的事件逐一进行响应。因此对于多路复用 IO 模型来说, 一旦事件响应体很大,那么就会导致后续的事件迟迟得不到处理,并且会影响新的事件轮询
  • 信号驱动IO模型:
    • 当用户线程发起一个 IO 请求操作,会给对应的 socket 注册一个信号函
      数,用户线程会继续执行,当内核数据就绪时会发送一个信号给用户线程,用户线程接收到信号之后,便在信号函数中调用 IO 读写操作来进行实际的 IO 请求操作
  • 异步IO模型:
    • 用户线程发起 read 操作之后,立刻就可以开始去做其它的事。从内核的角度,当它受到一个 asynchronous read 之后,会立刻返回,说明 read 请求已经成功发起了,因此不会对用户线程产生任何 block。内核会等待数据准备完成,然后将数据拷贝到用户线程,当这一切都完成之后,内核会给用户线程发送一个信号,告诉它 read 操作完成了。
    • 用户线程只需要先发起一个请求,当接收内核返回的成功信号时表示 IO 操作已经完成,可以直接去使用数据了。
    • 异步 IO 模型中, IO 操作的两个阶段都不会阻塞用户线程,这两个阶段都是由内核自动完成,然后发送一个信号告知用户线程操作已完成。用户线程中不需要再次调用 IO 函数进行具体的读写。
      • 在信号驱动模型中,当用户线程接收到信号表示数据已经就绪,然后需要用户线程调用 IO 函数进行实际的读写操作;
      • 在异步 IO 模型中,收到信号表示 IO 操作已经完成,不需要再在用户线程中调用 IO 函数进行实际的读写操作。
  • java NIO
    • 三大核心部分: Channel(通道)、Buffer(缓冲区)、Selector
    • 数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。Selector(选择区)用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个线程可以监听多个数据通道。
    • NIO 和传统 IO 之间区别是, IO 是面向流的, NIO 是面向缓冲区的
    • 缓冲区
      • Java IO 面向流:每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方。此外,它不能前后移动流中的数据。如果需要前后移动从流中读取的数据, 需要先将它缓存到一个缓冲区。
      • NIO :数据读取到一个稍后处理的缓冲区,需要时可在缓冲区中前后移动。增加了处理过程中的灵活性。但是,需检查是否该缓冲区中包含所有需要处理的数据。而且,需确保当更多的数据读入缓冲区时,不要覆盖缓冲区里尚未处理的数据
    • 非阻塞
      • IO 的各种流是阻塞的。当一个线程调用 read() 或 write()时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了。
      • NIO 的非阻塞模式,使一个线程从某通道发送请求读取数据,但仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取。而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事情。 非阻塞写也是如此。一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。 线程通常将非阻塞 IO 的空闲时间用于在其它通道上
        执行 IO 操作,所以一个单独的线程现在可以管理多个输入和输出通道(channel)。
    • channel:Channel 和 IO 中的 Stream(流)是差不多一个等级的。
      • Stream 是单向的: InputStream, OutputStream,
      • Channel 是双向的,既可以用来进行读操作,又可以用来进行写操作。主要实现有:FileChannel、DatagramChannel、SocketChannel、ServerSocketChannel分别可以对应文件 IO、 UDP 和 TCP(Server 和 Client)。
    • Buffer:缓冲区,一个连续数组,channel提供从文件、网络读取数据的渠道,但读取或写入的数据必须经由Buffer。
      • 客户端发送数据先将数据存到Buffer,然后将Buffer中的内容写入通道
      • 服务端接收数据通过Channel将数据读入到Buffer中,然后再从Buffer中取出数据来处理。
    • Selector:能够检测多个注册的通道上是否有事件发生,如果有时间发生,便获取事件然后针对每个事件进行相应的响应处理。一个单线程管理多个通道,管理多个连接。

8.JVM类加载机制

  • 类加载机制:加载,验证,准备,解析,初始化
  • 加载:会在内存中生成一个代表这个类的 java.lang.Class 对象, 作为方法区这个类的各种数据的入口。可以从 ZIP 包中读取(比如从 jar 包和 war 包中读取),也可以在运行时计算生成(动态代理),也可以由其它文件生成(比如将 JSP 文件转换成对应的 Class 类)。
  • 验证:主要目的是为了确保class文件的字节流中包含的信息是否符合当前虚拟机的要求,并且不会危害虚拟机自身安全
  • 准备:正式为类变量分配内存并设置类变量的初始值阶段,即在方法区中分配这些变量所使用的内存空间
  • 解析:虚拟机将常量池中的符号引用替换为直接引用的过程
    • 符号引用:引用的目标并不一定要已经加载到内存中。 各种虚拟机实现的内存布局可以各不相同,
    • 直接引用:指向目标的指针,相对偏移量或是一个能间接定位到目标的句柄。如果有了直接引用,那引用的目标必定已经在内存中存在
  • 初始化:类加载的最后阶段,真正执行类中定义的java程序代码
    • 执行类构造器方法的过程。

9.类加载器

  • 启动类加载器(Bootstrap ClassLoader): 负责加载 JAVA_HOME\lib 目录中的, 或通过-Xbootclasspath 参数指定路径中的, 且被虚拟机认可(按文件名识别, 如 rt.jar) 的类。
  • 扩展类加载器(Extension ClassLoader):负责加载 JAVA_HOME\lib\ext 目录中的,或通过 java.ext.dirs 系统变量指定路径中的类库。
  • 应用程序类加载器(Application ClassLoader):负责加载用户路径(classpath)上的类库。JVM 通过双亲委派模型进行类的加载, 也可以通过继承 java.lang.ClassLoader实现自定义的类加载器。

10.双亲委派

  • 类收到了类加载请求,他首先不会尝试自己去加载这个类,而是把这个请求委派给父类去完成,每一个层次类加载器都是如此,因此所有的加载请求都应该传送到启动类加载其中,
  • 只有当父类加载器反馈自己无法完成这个请求的时候(在它的加载路径下没有找到所需加载的Class), 子类加载器才会尝试自己去加载。
  • 好处是比如加载位于 rt.jar 包中的类 java.lang.Object,不管是哪个加载器加载这个类,最终都是委托给顶层的启动类加载器进行加载,这样就保证了使用不同的类加载器最终得到的都是同样一个 Object 对象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/30506.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

常见的服务器安全管理漏洞

常见的服务器安全管理漏洞 企业信息化技术的应用,以不可逆转。随着文件服务器、ERP管理软件等等在企业中生根发芽,应用服务器也逐渐在企业中普及起来。以前在企业中有一台应用服务器已经是了不起的事情,现在有两台、三台的,也不为…

【LeetCode】169. 多数元素

目录标题 2023-8-9 10:43:27 169. 多数元素 2023-8-9 10:43:27 public int majorityElement(int[] nums) {int minTimes nums.length / 2;Arrays.sort(nums);int pre 0;int last pre;while (last < nums.length) {if (nums[pre] ! nums[last]) {if (last - pre > min…

Docker 方式 部署 vue 项目 (docker + vue + nginx)

1.安装好 nginx 。 2. 把 vue 项目的源码克隆到确定目录下。用 git 管理&#xff0c;所以直接 git clone 到既定目录就行了。 如我的目录是&#xff1a;/root/jiangyu/projects/gentle_vue/gentle_vue_code 。 3. 项目打包&#xff1a; npm run build 复制 会自动生成 dist…

自然语言处理(Natural Language Processing,NLP)

自然语言处理(Natural Language Processing&#xff0c;NLP)是人工智能领域的一个重要分支&#xff0c;旨在使计算机能够理解、处理和生成人类自然语言。NLP 的目标是让计算机能够像人类一样有效地理解和交流&#xff0c;从而实现更自然、更智能的人机交互。 NLP的理解概括&…

详解推送Git分支时发生的 cannot lock ref 错误

在码云上建了一个项目仓库,分支模型使用 git-flow ,并在本地新建了一个功能分支 feature/feature-poll。后来在推送时发生错误,提示 cannot lock ref ...... 这样的错误信息。下面复盘一下具体过程和解决办法,以供参考。 在码云中建立仓库时,考虑到想按照 GitFlow 的模式…

两个状态的马尔可夫链

手动推导如下公式。 证明&#xff1a; 首先将如下矩阵对角化&#xff1a; { 1 − a a b 1 − b } \begin {Bmatrix} 1-a & a \\ b & 1-b \end {Bmatrix} {1−ab​a1−b​} (1)求如下矩阵的特征值&#xff1a; { 1 − a a b 1 − b } { x 1 x 2 } λ { x 1 x 2 }…

【心电图信号压缩】ECG信号压缩与通过三次样条近似重建的ECG信号压缩研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

unreal engine c++ 创建tcp server, tcp client

TCP客户端 TcpConnect.h // Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h" #include "Common/UdpSocketReceiver.h" #include "GameFramework/Actor.h"DECLARE_DELEGATE…

yumdownloader命令——yum下载rpm软件包到本地

如果想通过 yum 下载服务的软件包&#xff0c;而不需要进行安装的话&#xff0c;可以使用 yumdownloader 命令&#xff0c;yumdownloader 命令可以下载软件包的RPM文件到本地。 yumdownloader 命令在软件包 yum-utils 里面&#xff0c;需要保证yum-utils已安装。 yum install…

Stable Diffusion - 幻想 (Fantasy) 风格与糖果世界 (Candy Land) 的人物图像提示词配置

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/132212193 图像由 DreamShaper8 模型生成&#xff0c;融合糖果世界。 幻想 (Fantasy) 风格图像是一种以想象力为主导的艺术形式&#xff0c;创造了…

Electron学习1 安装环境与第一个程序

Electron学习1 安装环境与第一个程序 一、 Electron 简介二、安装 nvm三、安装nodejs四、安装nrm五、安装electron1. npm 初始化2. 创建 package.json3. 安装electron4. 创建一个页面5. 创建文件main.js6. 创建预加载器文件 preload.js7. 启动程序 六、打包 一、 Electron 简介…

Scala编程语言入门教程

Scala教程 方便个人学习和查阅 学习目标 Scala介绍 简介 Scala创始人Martin Odersky马丁奥德斯基 再回到我们的scala语言&#xff0c;在Scala官网https://www.scala-lang.org/介绍了其六大特征。 Java和scala可以混编 类型推测(自动推测类型) 并发和分布式&#xff08;Ac…

Ubuntu 22.04 安装docker

参考&#xff1a; https://docs.docker.com/engine/install/ubuntu/ 支持的Ubuntu版本&#xff1a; Ubuntu Lunar 23.04Ubuntu Kinetic 22.10Ubuntu Jammy 22.04 (LTS)Ubuntu Focal 20.04 (LTS) 1 卸载旧版本 非官方的安装包&#xff0c;需要先卸载&#xff1a; docker.io…

每日一学:什么是 Harbor ?

目录 什么是 Harbor &#xff1f; 一、Harbor 的优势 二、Harbor 架构构成 三、Core services 这是 Harbor 的核心功能 什么是 Harbor &#xff1f; Harbor 是 VMware 公司开源的企业级 Docker Registry 项目&#xff0c;其目标是帮助用户迅速搭建一个企业级的 Docker Reg…

VUE之JWT前后端分离认证,学生管理系统

参考资料: SpringBoot搭建教程 SpringCloud搭建教程 JWT视频教程 JWT官网 Vue视频教程 JWT视频参考资料、VUE视频资料,及前后端demo 特别有参考价值的JWT博客1 特别有参考价值的JWT博客2 cookie、localstorage和sessionStorage的区别1 cookie、localstorage和sessi…

Metamask登录方式集成

Metamask登录 https://www.toptal.com/ethereum/one-click-login-flows-a-metamask-tutorial#how-the-login-flow-works 参考&#xff1a; https://zh.socialgekon.com/one-click-login-with-blockchain 后端需要在用户表中增加address和nonce字段。兼容其他登录方式&#xff0…

【分布式技术专题】RocketMQ延迟消息实现原理和源码分析

痛点背景 业务场景 假设有这么一个需求&#xff0c;用户下单后如果30分钟未支付&#xff0c;则该订单需要被关闭。你会怎么做&#xff1f; 之前方案 最简单的做法&#xff0c;可以服务端启动个定时器&#xff0c;隔个几秒扫描数据库中待支付的订单&#xff0c;如果(当前时间-订…

国产芯力特SIT1024QHG四通道本地互联网络(LIN)收发器,可替代TJA1024HG

SIT1024Q 是一款四通道本地互联网络&#xff08;LIN&#xff09;物理层收发器&#xff0c;符合 LIN 2.0、LIN 2.1、LIN 2.2、 LIN 2.2A 、 ISO 17987-4:2016 (12V) 和 SAE J2602 标准。主要适用于使用 1kbps 至 20kbps 传输速 率的车载网络。 SIT1024Q 通过 TXDx 引…

【0805作业】Linux中 AB终端通过两根有名管道进行通信聊天(半双工)(全双工)

作业一&#xff1a;打开两个终端&#xff0c;要求实现AB进程对话【两根管道】 打开两个终端&#xff0c;要求实现AB进程对话 A进程先发送一句话给B进程&#xff0c;B进程接收后打印B进程再回复一句话给A进程&#xff0c;A进程接收后打印重复1.2步骤&#xff0c;当收到quit后&am…

桥接模式-java实现

桥接模式 桥接模式的本质&#xff0c;是解决一个基类&#xff0c;存在多个扩展维度的的问题。 比如一个图形基类&#xff0c;从颜色方面扩展和从形状上扩展&#xff0c;我们都需要这两个维度进行扩展&#xff0c;这就意味着&#xff0c;我们需要创建一个图形子类的同时&#x…