JVM基本常识了解

2024-03-25 03:20
文章标签 java jvm 了解 基本常识

本文主要是介绍JVM基本常识了解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1,JVM : Java Virtual Machine java虚拟机,实现跨平台工作的根本原因

2,JRE:Java Runtime Environment :Java运行时环境

整体来说属于运行时阶段

JVM分成三大块:

类加载模块,内存管理模块,执行引擎模块。

JVM两个版本:1,hotspot(商业)    2,openjdk(开源)

软件执行的技术支持:

硬件的支持:

CPU,内存,IO设备

核心:CPU时无法和设备之间直接打交道,只能和内存打交道。

开发人员开发的程序,是保存在硬盘上的。所以开发的程序是无法直接和CPU进行交互的。

为了解决这个问题,JVM的类加载子模块,会将数据从硬盘加载到内存中,解决这个问题。

类加载器(ClassLoader):

输入:一个类名称

输出:加载到内存中的类数据。

1,使用类加载的时机:

1),程序开始启动时,就将程序需要的所有的类加载到内存中。(启动慢,运行快,占内存)

2),程序在开始执行时,不加载,只有在需要使用的时候,才会加载到内存中。(启动快,运行慢,不需要太大的内存)

2,什么叫一个类被使用:

需要使用类的对象(new,和class对象),类的属性,类的静态方法,类的父类(接口)就叫类被使用。

3,类的名称:包名+类名

4,硬盘上的文件(文件系统树),类加载器是如何知道去哪里寻找这个类文件?

针对jdk提供的类:加载类的路径是绑定在JVM程序路径上的,由核心类加载器加载

针对应用类:启动的时候,通知JVM去哪里寻找类,通常写作 -classpath : 类的绝对路径,将需要的类的绝对路径加载到classpath中,第三方类也是保存在磁盘中,

5,JVM中针对不同的类,(默认情况下)设计了不同的类加载器

1),启动类加载器:负责加载常见的jdk提供的类,

2),应用类加载器:负责加载开发人员写的类和引入的第三方的类

3),扩展类加载器:负责加载jdk提供的不常见的类

6,类加载器可以加载类文件,类文件中保存了什么,是以什么结构进行组织的?

保存了:类的名字,父类,接口个数,哪些接口,类的常量池,属性个数,属性信息数组(以上是使用数据形式保存),类的方法信息(使用字节码保存)

 7,类加载过程中可以再次进行划分:

加载,1)验证类数据是否符合规范,2)文件的读操作,解析 3)将读取到的内容组织成一个逻辑整体‘类’,放在内存中

链接,:类与类之间存在关系,链接就是将加载到内存中的的类之间产生关系。

初始化:类的基本信息初始化,涉及:类的那些指令要被执行,执行的顺序是什么样的。

8,类的加载过程中,初始化的几个时机,按照什么顺序

静态属性               在类加载的时候执行一次

static{。。。}        在类加载的时候执行一次

加载顺序:按照代码的书写顺序加载

父类加载完成加载子类

9,类被加载到那个区域:方法区(字节码文件肯定放在这里区域)

10,类有没有可能会卸载(将类从内存中移除): 一个类没有被使用就会被卸载

11,

JVM如何确定唯一的类:累加器 + 类名

JVM支持自定义类加载(继承ClassLoad类,重写一些方法):Tomcat里面实现了自己的类加载器

双亲委派模型:

双亲:parent,只有一个(不是继承)

双亲委派:应用类加载器被指定加载一个类之前,应该先交给自己的双亲进行加载,如果双亲可以加载,使用双亲加载,否则自己再去加载。

执行引擎:类比成硬件中的cpu

JVM这里的执行引擎何线程是绑定的:JVM中的线程,类比cpu中的一个核,每个线程都有自己的pc:类比每个核都有自己的程序计数器。

当一个Java程序启动 时:

JVM内存管理模块GC

GC含义1:垃圾回收器,负责进行内存管理模块的组件

含义2:一次垃圾回收的过程

执行引擎在什么时候会用到内存:

1,实例化对象时(存数据),2,类加载时(存类信息),  3,当一个方法被执行时(局部变量) 4,常见一个线程时。

JVM的内存划分

1,方法区,                                        存放指令方法的

2,堆区,                                            存放对象

3,Java调用栈、本地方法调用栈        存储方法调用栈,局部变量

4,运行时常量池                                  存放类文件中的常量

5,pc                                                    每个线程独有的,存放下一条指令地址

划分区域的好处:

因为功能的区别,划分区域,可以方便的进行内存管理,更方便的做出不同的处理方式,

这几个区域那些是线程共享的,那些是私有的:

共享:堆区,方法区,运行时常量池

私有:方法栈,pc

PC在什么情况下,会分配内存?

      线程在被创建的时候

运行时常量池在什么情况下,会分配内存?

    类加载时

堆在什么情况下,会分配内存?

    对象在创建时

方法栈帧在什么情况下,会分配内存?

    方法被调用时

方法区在什么情况下,会分配内存?

   类加载时

PC在什么情况下,会回收内存?

      线程在被终止的时候

运行时常量池在什么情况下,会回收内存?

    类被卸载时

堆在什么情况下,会回收内存?

    对象在不在使用时

方法栈帧在什么情况下,会回收内存?

    方法调用结束时

方法区在什么情况下,会回收内存?

   类卸载时

明确回收的时机:

1,PC(线程被销毁),方法栈(方法执行结束)

方法区,运行时常量池,对象不在使用很难明确

关于堆上的垃圾回收

堆上的内存都是以对象管理的,所以堆的垃圾回收,都是回收对象

1,如何判定垃圾对象(那些对象不被使用)

靠引用的持有情况,如果一个对象的所有引用时都不被应用持有,那么就被判定为不在使用(理想情况下),事实上是做不到的,所以采用了退而求其次的做法,保证回收的都是垃圾对象,不保证所有的垃圾对象都被回收。

垃圾判断算法:

1,引用计数法:JVM中没有这么使用,但在PHP,C++的智能指针是这么实现的。

实现思想:给对象设计一个引用树refCount,维护对象被引用指向的次数

当首次new对象,引用之间赋值时,refCount++;

当引用变量出了作用域,静态属性,类被卸载时,refCOunt--;

当refCount == 0 时,就一定不会被用到,就可以判定为垃圾对象。

引用计数法存在着一个问题,是本身无法解决的:循环引用,

2,Hotspot采用可达性分析法

JVM管理的对象一定是使用图形进行管理起来的,

 

 我们将此(程序的出发点所包含的引用)看作为GC的根节点 GC Roots

GC在垃圾回收时,对象的可达结构不变,判断是否可以到达堆上的对象,如果不能够到达,就会判定为来及对象,等待回收。

GC Roots包含:所有的静态属性,当前线程中的栈帧所持有的引用。

引用的分类:

引用本身定义出来是通过引用找到对象,但是GC的出现,引用可以决定对象的生存,

所以按照对象回收的优先级,将引用划分成四个等级:

1,强引用:通过引用可以找到对象,对象不能被回收

2,软引用:通过引用找到对象,对象的回收优先级低,可以被回收(内存不够用时)

3,弱引用:通过引用找到对象,对象的回收优先级较低,可以回收(内存不共用时)

4,虚引用:仅在对象被回收时收到通知。

2,如何进行垃圾回收(垃圾回收算法)

GC在在每次为对资源的释放何分配,可以类比成一个线性表,分配资源是,将线性表的空间分配给对象,释放资源时,将线性表的空间释放。

这种方式会存在内存碎片的问题

存在三个空间,但是只能分配两个连续的空间,

解决方法1:整理+回收

将资源回收在整理,将内存复制删除后,使内存连续,这种方法,分配资源的的时间复杂度为O(1),回收的时间复杂度为O(n);

 

解决方法二: 分代算法

一个应用中创建的对象,大部分是短生命周期的对象 ,90%活不过一个GC

复制+回收算法:

 垃圾回收的分代流程:

 

 

3,什么情况进行垃圾回收

1,内存不够或者达到了空间阈值,就进行垃圾回收,GC不能够太频繁,也不能太频繁,因为GC的代价很大。

2,定期进行GC

FUll  GC (整个清理) = MInor GC(新生代GC)  + Major GC(老年代GC)

大部分GC,都是Minor  GC (新生代GC) ,所以耗时不高,但随着Minor GC,不断有新生代对象,进入老年代,老年代会触发阈值,导致老年代GC ,所以Major GC 一般都是会导致 FUll GC。

GC的各种算法,各有利弊,

这篇关于JVM基本常识了解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/843698

相关文章

JDK8(Java Development kit)的安装与配置全过程

《JDK8(JavaDevelopmentkit)的安装与配置全过程》文章简要介绍了Java的核心特点(如跨平台、JVM机制)及JDK/JRE的区别,重点讲解了如何通过配置环境变量(PATH和JA... 目录Java特点JDKJREJDK的下载,安装配置环境变量总结Java特点说起 Java,大家肯定都

Spring定时任务之fixedRateString的实现示例

《Spring定时任务之fixedRateString的实现示例》本文主要介绍了Spring定时任务之fixedRateString的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有... 目录从毫秒到 Duration:为何要改变?核心:Java.time.Duration.parse

Java 中 Optional 的用法及最佳实践

《Java中Optional的用法及最佳实践》在Java开发中,空指针异常(NullPointerException)是开发者最常遇到的问题之一,本篇文章将详细讲解Optional的用法、常用方... 目录前言1. 什么是 Optional?主要特性:2. Optional 的基本用法2.1 创建 Opti

docker编写java的jar完整步骤记录

《docker编写java的jar完整步骤记录》在平常的开发工作中,我们经常需要部署项目,开发测试完成后,最关键的一步就是部署,:本文主要介绍docker编写java的jar的相关资料,文中通过代... 目录all-docker/生成Docker打包部署文件配置服务A的Dockerfile (a/Docke

Java中实现对象的拷贝案例讲解

《Java中实现对象的拷贝案例讲解》Java对象拷贝分为浅拷贝(复制值及引用地址)和深拷贝(递归复制所有引用对象),常用方法包括Object.clone()、序列化及JSON转换,需处理循环引用问题,... 目录对象的拷贝简介浅拷贝和深拷贝浅拷贝深拷贝深拷贝和循环引用总结对象的拷贝简介对象的拷贝,把一个

Java 字符串操作之contains 和 substring 方法最佳实践与常见问题

《Java字符串操作之contains和substring方法最佳实践与常见问题》本文给大家详细介绍Java字符串操作之contains和substring方法最佳实践与常见问题,本文结合实例... 目录一、contains 方法详解1. 方法定义与语法2. 底层实现原理3. 使用示例4. 注意事项二、su

Spring Boot中获取IOC容器的多种方式

《SpringBoot中获取IOC容器的多种方式》本文主要介绍了SpringBoot中获取IOC容器的多种方式,包括直接注入、实现ApplicationContextAware接口、通过Spring... 目录1. 直接注入ApplicationContext2. 实现ApplicationContextA

详解Spring中REQUIRED事务的回滚机制详解

《详解Spring中REQUIRED事务的回滚机制详解》在Spring的事务管理中,REQUIRED是最常用也是默认的事务传播属性,本文就来详细的介绍一下Spring中REQUIRED事务的回滚机制,... 目录1. REQUIRED 的定义2. REQUIRED 下的回滚机制2.1 异常触发回滚2.2 回

Java 单元测试之Mockito 模拟静态方法与私有方法最佳实践

《Java单元测试之Mockito模拟静态方法与私有方法最佳实践》本文将深入探讨如何使用Mockito来模拟静态方法和私有方法,结合大量实战代码示例,带你突破传统单元测试的边界,写出更彻底、更独立... 目录Mockito 简介:为什么选择它?环境准备模拟静态方法:打破“不可变”的枷锁传统困境解法一:使用M

linux查找java项目日志查找报错信息方式

《linux查找java项目日志查找报错信息方式》日志查找定位步骤:进入项目,用tail-f实时跟踪日志,tail-n1000查看末尾1000行,grep搜索关键词或时间,vim内精准查找并高亮定位,... 目录日志查找定位在当前文件里找到报错消息总结日志查找定位1.cd 进入项目2.正常日志 和错误日