草庐IT

jvm相关知识

zmmijava 2023-03-28 原文

JVM相关知识

  • 内存结构
  •         第一部分:
    • 编译器(将.java源文件编译为.class文件)
    • 类加载器
      • 类加载实际上包括三部分:
        • 懒加载
        • 链接
        • 懒初始化
    • 第二部分:
      • 方法区(线程公有):方法区实际上是JVM的一种规范,它在HotSpot虚拟机(HSDB,Hotspot Debugger调试工具)中,在1.7之间存在于永久代中,在1.8中存在于元空间中,使用本地内存对这些信息进行存储
      • 堆内存(线程公有):jvm调优的重点区域,jvm参数  -Xmx -Xms   -Xmn .主要分为伊甸园、幸存区(from、to)、老年代.   Minor GC、Mixed GC、Full GC
      • 程序计数器(线程私有):程序计数器是唯一一个不存在内存溢出或内存泄漏的区域
      • 虚拟机栈(线程私有):虚拟机栈采用了栈的思想,分为多个栈帧,每一个栈帧对应一个方法。
        • 虚拟机栈中存在的内存泄漏有循环终止条件没有设计好,或者单个栈帧运行所需的空间足够大
        • 本地方法栈(线程私有):本地方法栈对应本地方法接口,调用本地方法中的参数。
    • 第三部分:执行引擎
      • 解释器:将.class字节码文件解释为计算机运行的机器码
      • 即时编译器(JIT):即时编译器会对热点代码的执行进行优化,并将优化后的存放在缓存中
      • GC垃圾回收器:JVM调优的根本,Gc大大地解放了程序员自身对于内存的管理,但仍存在一些问题。
    • 第四部分: 本地方法接口(操作系统、C++实现)
  • 内存模型
    • 内存模型实际上是jvm在多线程下和cpu之间交互的一种设计思想,主要体现为操作系统中的主内存和每个线程之间的高速缓冲区.第一次会从操作系统中读到高速缓存区中,下一次则直接从高速缓冲区中读取,但是进行写操作需要更新主内存后即时地更新(或删除)高速缓冲区的数据
  • 类加载器、双亲委派机制
    • 类加载器包括引导类加载器(根类加载器  / jre/lib包下)、扩展类加载器(/jre/lib/ext)、应用程序类加载器(/classpath)、自定义类加载器。
    • 双亲委派模型指的是加载类时,向上抛出,逐个加载直到能够加载则停止
  • 垃圾回收GC
    • 3种垃圾回收算法
      • 标记清除(速度快、会有内存碎片产生、现在的垃圾回收器已经弃用)
      • 标记整理(速度慢、没有内存碎片产生)
      • 标记复制(没有内存碎片产生、但是内存占用较大,且其中一份内存始终不存储数据)
    • 3种垃圾回收器
      • Parallel并行,注重吞吐量
      • CMS(Concurrent Modify Sweep)垃圾回收(使用标记清除),该回收器已经被弃用,注重响应时间。
      • G1垃圾回收器,同时注重了吞吐量和响应时间
        • 把堆内存分为很多大小相等的内存空间(64份???),每一份都能作为伊甸园、幸存区(合并了from to)、老年代
  • 四种引用
    • GC root、可达性分析、三色标记算法(标记过的、没有被标记的,正在进行分析标记的)
      • 强引用:被强引用,即普通的new一个对象的引用在垃圾回收时,是不会被回收的。(包括直接饮用的其内部的成员变量)
      • 软引用:  在第一次垃圾回收时,不会被回收,当再次垃圾回收的时候,就会被回收
      • 弱引用: 在第一次进行垃圾回收的时候,就会被回收。
      • 虚引用:在第一次进行垃圾回收的时候,就会被回收。
      • 引用队列:对于软引用、弱引用和虚引用来说,其创建的中间引用对象都可以加入到引用队列中,然后开启一个单独的线程处理该引用队列。其中虚引用是必须强制使用引用队列的。
      • ThreadLocal的内存泄漏和弱引用:
        • ThreadLocal中的key被设计为弱引用,因此其key可以被进行垃圾回收,但是回收之后,我们就存在无法根据key去手动remove其对应的value,而value却是强引用,此时就存在内存泄漏问题。
        • 其解决思路是:
        • 1.在使用完毕后,及时的手动移除value
        • 2.将弱引用加入到引用队列中,其中存储的是ThreadLocalMap中的Entry对象,通过将Entry对象置为null,实现key和value都被回收。
        • 3.Jdk9中对于2的实现原理进行了优化和封装,使用Cleaner对象(运行时是一个守护线程)
  • finalize方法剖析
      • finalize
        • 它是 Object 中的一个方法,如果子类重写它,垃圾回收时此方法会被调用,可以在其中进行资源释放和清理工作.
        • 但是将资源释放和清理放在 finalize 方法中非常不好,非常影响性能,严重时甚至会引起 OOM,从 Java9 开始就被标注为 @Deprecated,不建议被使用了
        • finalize 原理
          • finalize 方法进行处理的核心逻辑位于 java.lang.ref.Finalizer 类中,它包含了名为 unfinalized 的静态变量(双向链表结构),Finalizer 也可被视为另一种引用对象(地位与软、弱、虚相当,只是不对外,无法直接使用)
          • 当重写了 finalize 方法的对象,在构造方法调用之时,JVM 都会将其包装成一个 Finalizer 对象,并加入 unfinalized 链表中
            • Finalizer 类中还有另一个重要的静态变量,即 ReferenceQueue 引用队列,刚开始它是空的。当狗对象可以被当作垃圾回收时,就会把这些狗对象对应的 Finalizer 对象加入此引用队列
            • 但此时 Dog 对象还没法被立刻回收,因为 unfinalized -> Finalizer 这一引用链还在引用它嘛,为的是【先别着急回收啊,等我调完 finalize 方法,再回收】
            • FinalizerThread 线程会从 ReferenceQueue 中逐一取出每个 Finalizer 对象,把它们从链表断开并真正调用 finallize 方法
            • 由于整个 Finalizer 对象已经从 unfinalized 链表中断开,这样就会在下次 gc 时就被回收了
        • finalize 缺点
          • 无法保证资源释放:FinalizerThread 是守护线程,代码很有可能没来得及执行完,线程就结束了
          • 无法判断是否发生错误:执行 finalize 方法时,会吞掉任意异常(Throwable)
          • 内存释放不及时:重写了 finalize 方法的对象在第一次被 gc 时,并不能及时释放它占用的内存,因为要等着 FinalizerThread 调用完 finalize,把它从 unfinalized 队列移除后,第二次 gc 时才能真正释放内存
          • 有的文章提到【Finalizer 线程会和我们的主线程进行竞争,不过由于它的优先级较低,获取到的CPU时间较少,因此它永远也赶不上主线程的步伐】这个显然是错误的,FinalizerThread 的优先级较普通线程更高,原因应该是 finalize 串行执行慢等原因综合导致
  • 内存溢出的几种情况
    • 典型情况
      • 误用线程池导致的内存溢出
        • 使用了不推荐的线程池创建
          • 固定线程数的线程池(Executors.newFixedThreadPool,其中的工作队列是近似没有上限的(Integer的最大值))
          • 带有缓存的线程池(Executors.newCachedThreadPool,其中的核心线程数为0,全部都是救济线程(Integer的最大值)
        • 单次查询数据量太大(禁止调用查询全表的数据接口)导致的内存溢出,进行分页查询(limit)
        • 动态生成类导致的内存溢出(动态生成的类使用了自定义的类加载器,其中的静态成员变量是强引用,不能被垃圾回收,应该将静态变量修改为成员变量)

有关jvm相关知识的更多相关文章

  1. ruby-on-rails - 相关表上的范围为 "WHERE ... LIKE" - 2

    我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que

  2. ruby-on-rails - 在具有 ActiveRecord 条件的相关模型中按字段排序 - 2

    我正在尝试按Rails相关模型中的字段进行排序。我研究的所有解决方案都没有解决如果相关模型被另一个参数过滤?元素模型classItem相关模型:classPriority我正在使用where子句检索项目:@items=Item.where('company_id=?andapproved=?',@company.id,true).all我需要按相关表格中的“位置”列进行排序。问题在于,在优先级模型中,一个项目可能会被多家公司列出。因此,这些职位取决于他们拥有的company_id。当我显示项目时,它是针对一个公司的,按公司内的职位排序。完成此任务的正确方法是什么?感谢您的帮助。PS-我

  3. ruby - 我怎样才能更好地了解/了解更多关于 Ruby 的知识? - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。我最近开始学习Ruby,这是我的第一门编程语言。我对语法感到满意,并且我已经完成了许多只教授相同基础知识的教程。我已经写了一些小程序(包括我自己的数组排序方法,在有人告诉我谷歌“冒泡排序”之前我认为它非常聪明),但我觉得我需要尝试更大更难的东西来理解更多关于Ruby.关于如何执行此操作的任何想法?

  4. ruby - 使用指向 ruby​​ 可执行文件的符号链接(symbolic link)时查找相关库 - 2

    假设您有一个可执行文件foo.rb,其库bar.rb的布局如下:/bin/foo.rb/lib/bar.rb在foo.rb的header中放置以下要求以在bar.rb中引入功能:requireFile.dirname(__FILE__)+"../lib/bar.rb"只要对foo.rb的所有调用都是直接的,这就可以正常工作。如果你把$HOME/project和符号链接(symboliclink)foo.rb放入$HOME/usr/bin,然后__FILE__解析为$HOME/usr/bin/foo.rb,因此无法找到bar.rb关于foo.rb的目录名.我意识到像ruby​​gems这

  5. HarmonyOS原子化服务开发相关术语 - 2

    术语中文解释Ability原子化服务帮助用户完成任务的原子化服务,和用户的意图进行关联。Fulfillment服务履行通过图标,卡片,语音等形式呈现用户意图。开发者通过接口的方式,处理用户意图,返回内容。Intent意图用于表达用户想要达成的目标或完成的任务。HUAWEIAssistant智能助手“无微不智”的个人助手,通过不断的学习用户的使用习惯,不断的为用户提供贴心的精准的便捷的个性化服务。AISearch全局搜索用户可快速搜索关键词,与之匹配的原子化服务则会出现在搜索结果中。SmartService智慧服务用户订阅原子化服务,在到达特定触发条件(时间、地点、事件)后,卡片推送至用户智能助

  6. H2数据库配置及相关使用方式一站式介绍(极为详细并整理官方文档) - 2

    目录H2数据库入门以及实际开发时的使用1.H2数据库的初识1.1H2数据库介绍1.2为什么要使用嵌入式数据库?1.3嵌入式数据库对比1.3.1性能对比1.4技术选型思考2.H2数据库实战2.1H2数据库下载搭建以及部署2.1.1H2数据库的下载2.1.2数据库启动2.1.2.1windows系统可以在bin目录下执行h2.bat2.1.2.2同理可以通过cmd直接使用命令进行启动:2.1.2.3启动后控制台页面:2.1.3spring整合H2数据库2.1.3.1引入依赖文件2.1.4数据库通过file模式实际保存数据的位置2.2H2数据库操作2.2.1Mysql兼容模式2.2.2Mysql模式

  7. ruby-on-rails - 旧的 Ruby 错误在我的 Ruby on Rails 应用程序中反复出现,与 Class.create 和 delayed_job 相关 - 2

    这个错误已经有好几个月了,在这里:http://www.ruby-forum.com/topic/1094002其中显示代码更改的两个链接:https://github.com/godfat/ruby/commit/f4e0e8f781b05c767ad2472a43a4ed0727a75708https://github.com/godfat/ruby/commit/c7a6cf975d88828c2ed27d253f41c480f9b66ad6我有Ruby1.9.2和rvm。我会把这些更改粘贴到适当的文件中,但我不知道如何粘贴。这在几天前就奏效了。我不能像这样执行RubyonRai

  8. ruby - Ruby基础知识 - 2

    Asitcurrentlystands,thisquestionisnotagoodfitforourQ&Aformat.Weexpectanswerstobesupportedbyfacts,references,orexpertise,butthisquestionwilllikelysolicitdebate,arguments,polling,orextendeddiscussion.Ifyoufeelthatthisquestioncanbeimprovedandpossiblyreopened,visitthehelpcenter提供指导。已关闭8年。什么是学习ruby语言

  9. ruby-on-rails - Searchkick 结果不相关 - 2

    我对相关搜索有疑问。以下请求的结果很奇怪:Candidate.search('martin',fields:[:first_name,:last_name],match::word_start,misspellings:false).map(&:name)["KautzerMartina","FunkMartin","JaskolskiMartin","GutmannMartine","WiegandMartina","SchuellerMartin","DooleyMartin","StiedemannMartine","BartellMartina","GerlachMartine

  10. ruby-on-rails - 我该如何去追踪与 Bundler 相关的 DEPRECATION WARNING - 2

    我是Rails的新手。当我启动我的应用程序时,我不断看到这些弃用警告:DEPRECATIONWARNING:refisdeprecatedandwillberemovedfromRails3.2.(calledfromatD:/dev/AquaticKodiak/config/application.rb:12)DEPRECATIONWARNING:newisdeprecatedandwillberemovedfromRails3.2.(calledfromatD:/dev/AquaticKodiak/config/application.rb:12)好的,第12行是什么?这个:Bun

随机推荐