Java 类加载和实例化对象的过程

1. 类加载实例化过程

  1. 当我们编写完一个*.java类后。
  2. 编译器(如javac)会将其转化为字节码。
  3. 转化的字节码存储在.class后缀的文件中(.class 二进制文件)。
  4. 接下来在类的加载过程中虚拟机JVM利用ClassLoader读取该.class文件将其中的字节码加载到内存中。
  5. 基于这些字节码信息创建相应的Class Object.
  6. 每个类在JVM中只加载一次,故而每个类都对应着一个唯一的Class对象(Class Object).
  7. 这个对象包含了类的元信息(metadata),如类的名称、包名、父类、实现的接口、字段、方法、构造函数等。 
  8. class Objcect可以通过获取构造函数创建实例化的对象。

2. 类加载存储位置

  • 字节码文件:
    是Java源代码编译后的产物,它们以二进制的形式存储在文件系统中。 所以它并不存放于JVM的结构中。
  • Class Object:
    Class对象被存储在JVM的方法区(Method Area)中的元空间(Metaspace)里。
  • 实例化对象:
    存放于堆内存(Heap Memory) 

3.  JVM利用classloader进行类加载和类初始化的区别

在Java中,类加载(Class Loading)和类初始化(Class Initialization)是两个不同的阶段,它们在类生命周期中扮演着不同的角色。下面是这两个阶段的区别: 

  • 类加载(Loading):
    通过类的全名获取类的二进制数据。将这些数据转换成方法区的运行时数据结构。在内存中生成一个代表这个类的java.lang.Class对象,作为这个类的各种数据的入口。然而,类的初始化(即执行静态初始化代码和静态初始化块)是在类加载的最后阶段(初始化阶段)由 JVM 自行完成的。所以我们在使用类反射,如User.class 获取class对象时,它是不会去执行静态代码块的。
  • 类初始化(Class Initialization)
    类初始化,广义上将它类加载过程中的最后一步,只不过这一步是动态的,而不是由程序启动之初就加载的,只有当类被主动使用时才会发生。这个阶段会执行类的静态初始化代码(在声明类变量时指定的初始值和在静态代码块中指定的代码)。这个过程只会在JVM首次主动使用类时发生一次。

4. 结合第三点,补充说明为什么反射中Object.class 不加载静态代码块,而Class.forName("ClassName")会加载静态代码块 

Object.class 和 Class.forName("ClassName") 在触发类加载和初始化方面有不同的行为,这主要是因为它们使用的方式和上下文不同。

Object.class:
当你使用 Object.class 时,你实际上是在引用Java的根类Object的Class对象。由于Object类是Java运行时系统的一部分,并且它几乎总是在你开始执行任何Java代码之前就已经被加载和初始化了(因为其他所有的类都直接或间接地继承自Object类),所以当你引用Object.class时,它不会再次触发Object类的加载和初始化。 静态代码块只会在类首次被主动使用时执行,而由于Object类几乎总是已经在使用之前就被加载和初始化了,因此通过Object.class引用它不会再次触发静态代码块的执行。
Class.forName("ClassName"):
Class.forName("ClassName") 是一个用于动态加载类并触发其初始化的方法。当你调用这个方法并传入一个类名(作为字符串)时,JVM会尝试找到并加载这个类。如果类还没有被加载和初始化,JVM会首先加载这个类,然后触发其初始化过程,这包括执行静态代码块。 Class.forName() 方法的主要用途是在运行时动态地加载和使用类,而不需要在编译时就知道这个类的存在。由于它是在运行时动态加载类的,所以它总是会触发类的加载和初始化过程(如果类还没有被加载和初始化的话)。
总结来说,Object.class 不会运行静态代码块是因为Object类通常在你开始执行任何Java代码之前就已经被加载和初始化了,而Class.forName("ClassName") 会运行静态代码块是因为它用于在运行时动态地加载和初始化类。

5. 关于静态代码块初始化的几个关键点:

执行时机:静态代码块在类被加载到JVM时执行。这通常发生在类的第一次主动使用时,例如创建类的实例、访问类的静态字段或方法、反射调用类的方法等。 执行顺序:如果有多个静态代码块,它们将按照在源文件中出现的顺序执行。 与静态变量的关系:静态变量可以在静态代码块中初始化,也可以在声明时直接赋值。但是,如果静态变量在声明时直接赋值,那么该赋值操作会在静态代码块之前执行。 静态代码块与构造器:静态代码块在构造器之前执行。这是因为静态代码块属于类级别的初始化,而构造器属于对象级别的初始化。 线程安全:虽然静态代码块只执行一次,但在多线程环境下,JVM会确保静态代码块的线程安全性,即静态代码块会同步执行,不会被多个线程同时访问。但是,请注意,静态代码块中的代码本身并不是线程安全的,你仍然需要确保其中的代码在多线程环境下能够正确运行。 

6. 类中的静态代码块被初始化后保存在JVM的哪里?

在JVM中,类中的静态代码块(static code block)在初始化后被执行,但它们本身并不直接“保存”在JVM的某个特定区域。静态代码块中的代码逻辑在类加载时被执行一次,并且其执行结果(如静态变量的赋值)会被存储在JVM的以下区域:

  • 方法区(Method Area):
    类加载后,静态变量(包括在静态代码块中初始化的变量)会被存储在方法区中的静态变量区域。静态变量属于类变量,不属于对象实例的一部分,只会在类加载时初始化一次。
     
  • 堆内存(Heap Memory): 虽然静态代码块本身不直接存储在堆内存中,但是静态代码块中初始化的静态对象(如静态的数组、其他类的静态实例等)会存储在堆内存中。这些对象通过静态变量持有引用,静态变量则存储在方法区的静态变量区域中。
     
  • 常量池(Constant Pool):
    如果静态代码块中声明了static final常量,并且这些常量的值在编译时就能确定(即常量折叠),那么这些常量会被放入类的常量池中。常量池是方法区的一部分,用于存储编译期生成的各种字面量和符号引用。 需要注意的是,静态代码块只是类加载过程中的一个逻辑单元,用于在类加载时执行一些初始化操作。这些操作的结果(如静态变量的值)会被存储在JVM的相应区域中,而静态代码块本身并不作为一个独立的实体被保存。当类被加载并初始化后,静态代码块中的代码逻辑就完成了它的使命,后续的对象创建和方法调用都不会再次执行这些代码。 

7. java 类级别的初始化和对象级别的初始化的区别?

在Java中,类级别的初始化和对象级别的初始化是两个不同的概念,它们分别涉及类的静态部分和实例部分。以下是它们之间的主要区别:

类级别的初始化
执行时机:当类被JVM首次主动使用时,会触发类级别的初始化。这通常发生在创建类的第一个实例、访问类的静态字段或方法、或者通过反射调用类的方法等情况。
初始化内容:类级别的初始化包括执行静态代码块(static blocks)和初始化静态变量。静态代码块和静态变量的初始化顺序按照它们在源代码中出现的顺序进行。
执行次数:类级别的初始化只会在类首次被加载到JVM时执行一次,无论创建多少个类的实例,静态代码块都不会再次执行。
线程安全性:JVM会确保类级别的初始化是线程安全的,即静态代码块会同步执行,不会被多个线程同时访问。
对象级别的初始化
执行时机:当创建类的实例时,会触发对象级别的初始化。这通常通过调用类的构造函数来完成。
初始化内容:对象级别的初始化包括执行实例初始化块(instance blocks)和构造函数,以及初始化实例变量。实例初始化块和构造函数的执行顺序是:首先执行实例初始化块(按照它们在源代码中出现的顺序),然后执行构造函数。
执行次数:与类级别的初始化不同,对象级别的初始化会在每次创建类的实例时执行。
线程安全性:对象级别的初始化(即构造函数的执行)不是线程安全的。如果在多线程环境中创建类的实例,需要确保对共享资源的访问是同步的,以避免数据不一致或其他并发问题。
 

 

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

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

相关文章

DEV--C++小游戏(吃星星(1.2))

目录 吃星星(1.2) 该版本简介更新说明 分部代码 头文件命名空间变量 结构体 角色结构体 星星结构体 打印地图结构体 函数 函数声明 单人模式游戏函数 双人模式游戏函数 开始游戏函数 清屏函数 定点输出函数 隐藏光标函数 输入函数 单人…

【C++】<知识点> 标准和文件的输入输出

目录 一、输入输出操作 1. 相关的类 2. 标准流对象 3. istream类的成员函数 二、流操纵算子 1. 整数流的基数 2. 浮点数精度的流操纵算子 3. 域宽的流操纵算子 4. 其他的流操纵算子 5. 用户自定义流操纵算子 三、文件读写 1. 文本文件的读写 2. 二进制文件的读写 3. 文件读写…

编一个自己的万年历

编一个自己的万年历 前阶段突然想查一下某一天是星期几,于是自己编了一个[小程序][https://blog.csdn.net/weixin_41905135/article/details/138972055?spm1001.2014.3001.5501],但是功能很单一,就是单纯的查是星期几。(虽然用网…

Deep Residual Learning for Image Recognition--论文笔记

论文笔记 论文来源: Deep Residual Learning for Image Recognition 代码来源 还没上传 1论文摘要的翻译 深度神经网络更难训练。我们提出了一个残差学习框架,以简化比以前使用的网络深度大得多的网络的训练。我们明确地将层重新表述为参考层输入的…

十五、Python模块 1、(入门一定看!!!)「长期更新Python简单入门到适用」

首先什么是模块? 小伙伴们经常看我写的教程不难发现,前面我们用过几次模块就是sys的那个,其实python不仅标准库中包含了大量的模块(也被称之为准模块),还有大量的第三方模块,开发者也可以自己发…

Python学习---基于HTTP的服务端基础框架搭建案例

整体功能: 1 创建框架构建相关的文件夹 2 创建app,模块文件 3 在 app模块文件中创建application函数(用于处理请求) 4 将request_handler()中的处理逻辑交由app模块的application函数完成 5 app模块的 application函数返回响应报文 6 在application 文件夹中创建一个…

零基础HTML教程(34)--HTML综合实例

文章目录 1. 背景2. 开发流程2.1 网站功能设计2.2 建立网站目录结构2.3 开发首页2.2 生平简介页2.3 经典诗词页2.4 苏轼图集页2.5 留言板 3. 小结 1. 背景 通过前面33篇文章的学习,我们对HTML有了一个比较全面的了解。 本篇,我们编写一个网站实例&…

C++ RBTree封装mapset

目录 RBTreeNode的声明 RBTree结构 map结构 set结构 改造红黑树 迭代器类 迭代器成员函数 默认成员函数 Insert set map RBTreeNode的声明 template<class T> struct RBTreeNode {RBTreeNode<T>* _left;RBTreeNode<T>* _right;RBTreeNode<T>*…

心理咨询系统|心理咨询系统开发|心理咨询软件开发

在快节奏的现代生活中&#xff0c;心理健康问题越来越受到人们的关注。为了有效应对这些问题&#xff0c;心理咨询系统应运而生&#xff0c;它为人们提供了一个安全、便捷的平台&#xff0c;以寻求心理帮助和支持。本文将详细介绍心理咨询系统的功能、优势以及未来发展趋势。 …

vue项目实战 - 如果高效的实现防抖和节流

在Vue项目中&#xff0c;处理高频事件的优化至关重要&#xff0c;直接影响用户体验和应用性能。防抖&#xff08;Debounce&#xff09;和节流&#xff08;Throttle&#xff09;是两种常用且有效的方法&#xff0c;可以控制事件触发频率&#xff0c;减少不必要的资源消耗。如何在…

使用Word表格数据快速创建图表

实例需求&#xff1a;Word的表格如下所示&#xff0c;标题行有合并单元格。 现在需要根据上述表格数据&#xff0c;在Word中创建如下柱图。如果数据在Excel之中&#xff0c;那么创建这个图并不复杂&#xff0c;但是Word中就没用那么简单了&#xff0c;虽然Word中可以插入图表&a…

免费撸gpt-4o和各种大模型实用经验分享

项目 Github: https://github.com/MartialBE/one-api 先贴两张图&#xff1a; 说明 免费撸AI大模型,各位可以对照下面我给出的大模型记录表来填&#xff0c;key需要自己去拿&#xff0c;国内都需要手机号验证&#xff0c;如果你不介意。另外我在自己的博客放出免费API给大家…

自定义RedisTemplate序列化器

大纲 RedisSerializerFastJsonRedisSerializer自定义二进制序列化器总结代码 在《RedisTemplate保存二进制数据的方法》一文中&#xff0c;我们将Java对象通过《使用java.io库序列化Java对象》中介绍的方法转换为二进制数组&#xff0c;然后保存到Redis中。实际可以通过定制Red…

[emailprotected](2)核心概念-JSX

目录 1&#xff0c;什么是 jsx2&#xff0c;空标签3&#xff0c;通过大括号使用 js4&#xff0c;防止注入攻击5&#xff0c;元素的不可变性 官方文档 1&#xff0c;什么是 jsx Facebook 起草的 js 扩展语法。本质上是 js 对象&#xff0c;会被 babel 编译&#xff0c;最终转换…

根据多个坐标经纬度获取到中心点的经纬度,scala语言

文章目录 前言scala 代码 总结 前言 Scala 语言 通过多个经纬度坐标点, 计算出中心点, 这里使用的是 Scala 语言,其他的语言需要自行转换。求出来的并不是原有的点&#xff0c;而是原有点的中心位置的点。 scala 代码 package com.dw.process.midimport java.lang.Double.pa…

【test】Windows11下通过sshfs挂载远程服务器目录

下载安装下面三个软件&#xff1a; sshfs-win&#xff1a;https://github.com/billziss-gh/sshfs-win/releases winfsp&#xff1a;https://github.com/billziss-gh/winfsp/releases SSHFS-Win Manager&#xff1a;https://github.com/evsar3/sshfs-win-manager/releases 安装…

数据结构---优先级队列(堆)

博主主页: 码农派大星. 数据结构专栏:Java数据结构 关注博主带你了解更多数据结构知识 1. 优先级队列 1.1 概念 前面介绍过队列&#xff0c;队列是一种先进先出(FIFO)的数据结构&#xff0c;但有些情况下&#xff0c;操作的数据可能带有优先级&#xff0c;一般出队 列时&am…

python低阶基础100题(上册)

** python低阶基础100题&#xff08;上册&#xff09; ** 1. 请打印出字符串 Hello World print("Hello World")2. 请打印出字符串 爸爸妈妈&#xff0c;你们辛苦啦 print("爸爸妈妈&#xff0c;你们辛苦啦")3. 请打印出字符串 人生苦短&#xff0c;我…

如何使用Studio 3T导出MongoDB数据成excel?

导出MongoDB查询集合数据成excel 1. 新建查询页面&#xff0c;输入指定的查询语句&#xff0c;执行查询获取结果。 这里以查询集合accountbackLogger表中的reqTime字段日期是2024年5月的数据为列。 db.getCollection("accountbackLogger").find({reqTime:{$gte: IS…

UE4/UE5像素流送云推流:多人访问不稳定、画面糊、端口占用多等

UE4/UE5想要实现网页访问&#xff0c;很多工程师会选择guan方的像素流送。但这个技术要求在模型开发初期就接入。对于一些已有UE模型是无法进行流化的。虽然也可以解决新UE模型的网页访问问题&#xff0c;但在实际的应用中&#xff0c;点量云流也收到很多反馈说&#xff0c;使用…