关于 JVM

1、请你谈谈你对JVM的理解?


        JVM由JVM运行时数据区(图示中蓝色框包含部分)、执行引擎、本地库接口、本地方法库组成。

        JVM运行时数据区,分为方法区、堆、虚拟机栈、本地方法栈和程序计数器。

        1.方法区
         Java 虚拟机规范中定义方法区是堆的一个逻辑部分。方法区存放以下信息:已经被虚拟机加载的类信息,常量,静态变量,即时编译编译器编译后的代码。线程共享的区域。为了与堆区分,方法还有一个别名:Non-Heap(非堆)。

        2.堆
        堆是用来存放对象的内存空间,几乎所有的对象都存储在堆中。这一区域是线程共享,整个 Java 虚拟机只有一个堆,所有的线程都访问同一个堆。

在 Java 中,堆被划分成两个不同的区域:新生代 ( Young )、老年代 ( Old )。新生代 ( Young ) 又被划分为三个区域:Eden、From Survivor、To Survivor。

这样划分的目的是为了使 JVM 能够更好的管理堆内存中的对象,包括内存的分配以及回收
 

        3.虚拟机栈
        Java 虚拟机栈是描述 Java 方法运行过程的内存模型。Java 虚拟机栈会为每一个即将运行的 Java 方法创建一块叫做“栈帧”的区域,用于存放该方法运行过程中的一些信息,比如:局部变量表,操作数栈,动态链接,方法出口信息等,方法执行的过程即为栈帧压栈出栈的过程。

        4.本地方法栈
        本地方法栈是为 JVM 运行 Native 方法准备的空间,由于很多 Native 方法都是用 C 语言实现的,所以它通常又叫 C 栈。它与 Java 虚拟机栈实现的功能类似,只不过本地方法栈是描述本地方法运行过程的内存模型。

        5.程序计数器
       程序计数器是一块较小的内存空间,是当前线程正在执行的那条字节码指令的地址。若当前线程正在执行的是一个本地方法,那么此时程序计数器为Undefined。

        这几部分都有相关的JDK自带工具可以分析查看,比如jps, jstack, jmap, jhat, jstat等,还有图形化工具jconsole,jvisualvm,但对于Linux服务器就无能为力了。

2、说一下新生代、老年代、永久代


JVM中的堆一般分为三大部分:新生代、老年代、永久代,其大致的占比如下:

 一、新生代

  新生代主要用来存放新生的对象。一般占据堆空间的1/3。在新生代中,保存着大量的刚刚创建的对象,但是大部分的对象都是朝生夕死,所以在新生代中会频繁的进行 MinorGC,进行垃圾回收,新生代又细分为三个区:Eden区、SurvivorFrom、SurvivorTo区,三个区的默认比例为:8:1:1。

 Eden区:Java新创建的对象绝大部分会分配在Eden区(如果对象太大,则直接分配到老年代)。当Eden区内存不够的时候,就会触发MinorGC(新生代采用的是复制算法),对新生代进行一次垃圾回收。
SurvivorFrom区和To区:在GC开始的时候,对象只会存在于Eden区和名为From的Survivor区,To区是空的,一次MinorGc过后,Eden区和SurvivorFrom区存活的对象会移动到SurvivorTo区中,然后会清空Eden区和SurvivorFrom区,并对存活的对象的年龄+1,如果对象的年龄达到15,则直接分配到老年代。MinorGC完成后,SurvivorFrom区和SurvivorTo区的功能进行互换。下一次MinorGC时,会把SurvivorTo区和Eden区存活的对象放入SurvivorFrom区中,并计算对象存活的年龄。
二、老年代

  老年代主要存放应用中生命周期长的内存对象。老年代比较稳定,不会频繁的进行MajorGC。而在MaiorGC之前才会先进行一次MinorGc,使得新生的对象进入老年代而导致空间不够才会触发。当无法找到足够大的连续空间分配给新创建的较大对象也会提前触发一次MajorGC进行垃圾回收腾出空间。

  在老年代中,MajorGC采用了标记—清除算法:首先扫描一次所有老年代里的对象,标记出存活的对象,然后回收没有标记的对象。MajorGC的耗时比较长。因为要扫描再回收。MajorGC会产生内存碎片,当老年代也没有内存分配给新来的对象的时候,就会抛出OOM(Out of Memory)异常。

三、永久代

  永久代指的是永久保存区域。主要存放 Class 和 Meta(元数据)的信息。Class 在被加载的时候被放入永久区域,它和存放的实例的区域不同,在Java8中,词锋代已经被移除,取而代之的是一个称之为“元数据区”(元空间)的区域。元空间和永久代类似,都是对JVM中规范中方法的实现。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存的限制。类的元数据放入native memory,字符串池和类的静态变量放入java堆中。这样可以加载多少类的元数据就不再由 MaxPermSize 控制,而由系统的实际可用空间来控制。

采用元空间而不用永久代的原因:

① 为了解决永久代的OOM问题,元数据和 class对象存放在永久代中,容易出现性能问题和内存溢出。
② 类及方法的信息等比较难确定其大小,因此对于永久代大小指定比较困难,太小容易出现永久代溢出,太大容易导致老年代溢出(堆内存不变,此消彼长)。
③ 永久代会为GC带来不必要的复杂度,并且回收效率偏低。

3、jvm的类加载机制?


一、jvm类加载机制的5个阶段:
      加载——连接(验证-准备-解析)——初始化——使用——卸载。

二、类加载器

1、jvm提供了三种类加载器:

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

2、双亲委派

当一个类收到了类加载请求,他首先不会尝试自己去加载这个类,而是把这个请求委派给父类去完成,每一个层次类加载器都是如此,因此所有的加载请求都应该传送到启动类加载其中,只有当父类加载器反馈自己无法完成这个请求的时候(在它的加载路径下没有找到所需加载的Class),子类加载器才会尝试自己去加载。

采用双亲委派的一个好处是不管是哪个加载器加载这个类,最终都是委托给顶层的启动类加载器进行加载,这样就保证了使用不同的类加载器最终得到的都是同样一个 Object 对象。


4、JVM调优经验


JVM配置方面
① -Xms 和 -Xmx 的值设置成相等,堆大小默认为-Xms指定的大小,默认空闲堆内存小于40%时,JVM会扩大堆到-Xmx指定的大小;空闲堆内存大于70%时,JVM会减小堆到-Xms指定的大小。如果在Full GC后满足不了内存需求会动态调整,这个阶段比较耗费资源。

② 新生代尽量设置大一些,让对象在新生代多存活一段时间,每次Minor GC 都要尽可能多的收集垃圾对象,防止或延迟对象进入老年代的机会,以减少应用程序发生Full GC的频率。

③ 老年代如果使用 CMS收集器,新生代可以不用太大,因为CMS的并行收集速度也很快,收集过程比较耗时的并发标记和并发清除阶段都可以与用户线程并发执行。

④ 方法区大小的设置,1.6之前的需要考虑系统运行时动态增加的常量、静态变量等,1.7只要差不多能装下启动时和后期动态加载的类信息就行。

代码实现方面
性能出现问题比如程序等待、内存泄漏除了JVM配置可能存在问题,代码实现上也有很大关系:

① 避免创建过大的对象及数组:过大的对象或数组在新生代没有足够空间容纳时会直接进入老年代,如果是短命的大对象,会提前出发Full GC。

② 避免同时加载大量数据,如一次从数据库中取出大量数据,或者一次从Excel中读取大量记录,可以分批读取,用完尽快清空引用。

③ 当集合中有对象的引用,这些对象使用完之后要尽快把集合中的引用清空,这些无用对象尽快回收避免进入老年代。

④ 可以在合适的场景(如实现缓存)采用软引用、弱引用,比如用软引用来为ObjectA分配实例:SoftReference objectA=new SoftReference(); 在发生内存溢出前,会将objectA列入回收范围进行二次回收,如果这次回收还没有足够内存,才会抛出内存溢出的异常。 
避免产生死循环,产生死循环后,循环体内可能重复产生大量实例,导致内存空间被迅速占满。

⑤ 尽量避免长时间等待外部资源(数据库、网络、设备资源等)的情况,缩小对象的生命周期,避免进入老年代,如果不能及时返回结果可以适当采用异步处理的方式等。

5、JDK 中常用的设计模式有哪些?


1、单例模式
作用:保证类只有一个实例。

JDK中体现:Runtime类。

2、静态工厂模式
作用:代替构造函数创建对象,方法名比构造函数清晰。

JDK中体现:Integer.valueOf、Class.forName

3、抽象エ厂
作用:创建某一种类的对象。

JDK中体现:Java.sql包。

4、原型模式
clone();

原型模式的本质是拷贝原型来创建新的对象,拷贝是比new更快的创建对象的方法,当需要大批量创建新对象而且都是同一个类的对象的时候考虑使用原型模式。

一般的克隆只是浅拷贝(对象的hash值不一样,但是对象里面的成员变量的hash值是一样的)。

有些场景需要深拷贝,这时我们就要重写clone方法,以ArrayList为例:

5、适配器模式
作用:使不兼容的接口相容。

JDK中体现:InputStream、OutputStream.

6、装饰器模式
作用:为类添加新的功能,防止类继承带来的类爆炸。

JDK中体现:io类、Collections、List。

7、外观模式
作用:封装一组交互类,一直对外提供接口。

JDK中体现:logging包。

8、享元模式

作用:共享对象、节省内存。

JDK中体现:Integer.valueOf、String常量池。

9、代理模式
作用:

(1)透明调用被代理对象,无须知道复杂实现细节:

(2)增加被代理类的功能;

JDK中体现:动态代理。

10、迭代器模式
作用:将集合的迭代和集合本身分离。

JDK中体现:terator

11、命令模式
作用:封装操作,使接口一致。

JDK中体现:Runable、Callable、ThreadPoolExecutor。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

YOLOv8-Seg改进:SPPF涨点篇 |引入YOLOv9的SPPELAN

🚀🚀🚀本文改进:SPP创新结合ELAN,来自于YOLOv9,助力YOLOv8,将SPPELAN代替原始的SPPF 🚀🚀🚀YOLOv8-seg创新专栏:http://t.csdnimg.cn/KLSdv 学姐带你学习YOLOv8,从入门到创新,轻轻松松搞定科研; 1)手把手教你如何训练YOLOv8-seg; 2)模型创新,提升分割…

day59 线程

创建线程的第二种方式 实现接口Runnable 重写run方法 创建线程的第三种方式 java.util.concurrent下的Callable重写call()方法 java.util.concurrent.FutureTask 创建线程类对象 获取返回值 线程的四种生命周期 线程的优先级1-10 default为5,优先级越高&#xff0c…

JavaEE进阶(15)Spring原理:Bean的作用域、Bean的生命周期、Spring Boot自动配置(加载Bean、SpringBoot原理分析)

接上次博客:JavaEE进阶(14)Linux基本使用和程序部署(博客系统部署)-CSDN博客 目录 关于Bean的作用域 概念 Bean的作用域 Bean的生命周期 源码阅读 Spring Boot自动配置 Spring 加载Bean 问题描述 原因分析 …

JavaEE企业开发新技术

目录 2.1 Class对象基本概念 1、概念 2.2 Class对象的获取方式 2.3基本数据类型的Class对象 1、概念 2.4 反射的基本概念 概念 2.5 Class对象的基本使用-1 2.6 Class对象的基本使用-2 newInstance()和new()区别: 2.1 Class对象基本概念 1、概念 反射的…

面试经典150题——合并两个有序链表

You just work on it. Time will do the rest! 1. 题目描述 2. 题目分析与解析 2.1 思路一 这个题目还是比较简单的,通过分析题目,我们可以知道题目中关键信息为: 所以我们只需要从前向后遍历两个链表,在两个链表不空的情况下&…

白皮书发布|超融合运行 K8s 的场景、功能与优势

目前,不少企业都使用虚拟化/超融合运行 Kubernetes 和容器化应用。一些用户可能会有疑惑:既然 Kubernetes 可以部署在裸金属上,使用虚拟化不是“多此一举”吗? 在电子书《IT 基础架构团队的 Kubernetes 管理:从入门到…

Android中显式Intent和隐式Intent的区别

1、intent的中文名 称是意图,Intent是各个组件之间信息沟通的桥梁, 既能在Activity之间沟通,又能在Activity与Service之间沟通,也能在Activity与Broadcast之间沟通 **intent组成元素的列表说明**2、显式Intent,直接指定…

河北专升本(C语言编程题)

一:基础算法原理 1. 冒泡排序 原理:从左到右,相邻元素进行比较。每次比较一轮,就会找到序列中最大的一个或最小的一个。这个数就会从序列的最右边冒出来。 以从小到大排序为例,第一轮比较后,所有数中最大的…

软考71-上午题-【面向对象技术2-UML】-UML中的图2

一、用例图 上午题,考的少;下午题,考的多。 1-1、用例图的定义 用例图展现了一组用例、参与者以及它们之间的关系。 用例图用于对系统的静态用例图进行建模。 可以用下列两种方式来使用用例图: 1、对系统的语境建模&#xff1b…

自动驾驶革命:解密端到端背后的数据、算力和AI奇迹

作者 |毫末智行数据智能科学家 贺翔 编辑 |祥威 最近,特斯拉FSD V12的发布引发了业界对端到端自动驾驶的热议,业界纷纷猜测FSD V12的强大能力是如何训练出来的。从马斯克的测试视频可以大致归纳一下FSD V12系统的一些核心特征: 训练数据&am…

Redis的集群模式

Redis有三种主要的集群模式,用于在分布式环境中实现高可用性和数据复制。这些集群模式分别是:主从复制(Master-Slave Replication)、哨兵模式(Sentinel)和Redis Cluster模式。 主从模式 主从复制是Redis最简单的集群模式。这个模式主要是为了解决单点故障的问题&a…

探索Cglib:解析动态代理的神奇之处

文章目录 CGLIB介绍CGLIB使用示例CGLIB核心原理分析代理类分析代理方法分析 FastClass机制分析 CGLIB介绍 CGLIB(Code Generation Library)是一个开源项目!是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与…

【echarts】xAxis鼠标事件失效问题

项目中用到echarts柱状图,出现x轴标签文字过长重叠问题,在pass掉标签倾斜、换行方案之后最终决定限制文字长度,超出以…占位,鼠标悬浮时显示完整tooltip。 但编写过程中发现xAxis鼠标事件无法触发,只有bar区域是可触发…

19 卷积层【李沐动手学深度学习v2课程笔记】

目录 1. 从全连接到卷积 2. 卷积层 3. 图像卷积代码 3.1 互相关运算 3.2 实现二维卷积层 3.3 图像中目标的边缘检测 3.4 学习卷积核 4. 小结 1. 从全连接到卷积 在欧几里得几何中,平移是一种几何变换,表示把一幅图像或一个空间中的每一个点在相同…

mysql中insert … select锁范围

1、执行 insert … select 的时候,对目标表也不是锁全表,而是只锁住需要访问的资源。 例如, CREATE TABLE t (id int(11) NOT NULL AUTO_INCREMENT,c int(11) DEFAULT NULL,d int(11) DEFAULT NULL,PRIMARY KEY (id),UNIQUE KEY c (c) ) EN…

streamlit初学-用streamlit实现云台控制界面

用streamlit实现云台控制界面 效果图PC上的效果手机上的效果 源码: 本文演示了,如何用streamlit做一个云台控制界面。功能包括:用户登录,事件的处理,图片的更新 版本信息: streamlit_authenticator: 下载链接streamlit : 1.31.1python: 3.11 修改点: streamlit_authenticato…

【嵌入式】字体极限瘦身术:Fontmin在嵌入式UI中的魔法应用(附3500常用汉字)

1. 概述 在嵌入式系统的用户界面(UI)设计中,字体的选择和优化至关重要。一个恰当的字体不仅能够提升用户体验,还能彰显产品特色。然而,由于嵌入式设备常常受限于存储空间和处理能力,大型字体文件可能成为性…

arkTS语法

lineHeight与css不同? 1、arkTS是什么 在继承了TS语法的基础上,主要扩展了声明式UI开发相关的能力 声明式UI是一种编写用户界面的范式。 2、声明组件的完整语法 3、自定义组件的语法使用 struct arkTS新增的关键字,是用于自定义组件或者自…

餐饮行业咨询数据在哪里查找?

1.中国饭店协会:国资委和商务部等政府指导发展,参与制定行业国家标准、行业标准与行业自律规则。按月出版《中国饭店业》会员刊物、及时更新协会官方网站和官方微信,方便会员单位及时掌握国内外饭店与餐饮业的最新动态。宣传企业经典案例、反…

使用jquery的autocomplete属性实现联想补全操作

平时使用百度,淘宝等软件搜索时,常见一个搜索框联想提示,感觉确实好用但没有研究过原理,最近恰巧工作中遇到一个同样的场景,不同于大厂使用高端的Python,这次需要使用jQuery的autocomplete属性来自动联想补…