当前位置: 首页 > news >正文

【JVM】详解对象的创建过程

文章目录

  • 1、创建对像的几种方式
    • 1、new关键字
    • 2、反射
    • 3、clone
    • 4、反序列化
  • 2、创建过程
    • 步骤 1、检查类是否已经被加载
    • 步骤 2、 为对象分配内存空间
      • 1、指针碰撞
        • 针对指针碰撞线程不安全,有两种方案:
      • 2、空闲列表
      • 选择哪种分配方式
    • 步骤3、将内存空间初始化为零值
    • 步骤4、对对象进行必要的设置
    • 步骤5、执行实例的初始化方法init
  • 总结
  • 注意

谈对象的创建过程的话,先来介绍介绍创建对象的几种方式

1、创建对像的几种方式

1、new关键字

通过调用类的构造方法创建对象
在这里插入图片描述

2、反射

通过反射创建对象的方式又有两种:
一种是通过Class.newInstance
在这里插入图片描述

另一种是通过调用构造器再去创建对象Constructor.newInstance:
先通过反射获取类中无参构造器,然后通过newInstance()获取对象
在这里插入图片描述

3、clone

通过Clone创建对象,首先实体类中必须先实现Cloneable接口并复写Object的clone方法(因为Object的这个方法是protected的)
在这里插入图片描述
在这里插入图片描述

4、反序列化

序列化:指把 Java 对象转换为字节序列的过程;
反序列化:指把字节序列恢复为 Java 对象的过程;
此方式需要类先实现Serializable接口

public class UserParam implements Serializable
public class Test {public static void main(String[] args) throws IOException, ClassNotFoundException {File file =new File("E:/Serializable.txt");FileOutputStream fileOutputStream = new FileOutputStream(file);ObjectOutputStream outputStream = new ObjectOutputStream(fileOutputStream);UserParam userParam =new UserParam("aaaa");outputStream.writeObject(userParam);FileInputStream fileInputStream  = new FileInputStream(file);ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);UserParam userParam1 = (UserParam)objectInputStream.readObject();userParam1.setNickName("bbbbbbb");System.out.println(userParam1);}}

通过阅读上面介绍的几种创建对象的方法,大家一定对new、newInstance背后的工作产生了好奇,那么下面我将介绍创建一个对象的流程:

2、创建过程

当Java虚拟机遇到一条字节码new指令时

步骤 1、检查类是否已经被加载

去常量池中查找该引用所指向的类有没有被虚拟机加载,如果没有被加载,那么会进行类的加载过程。类的加载过程需要经历:加载、链接、初始化三个阶段。对象的大小,在类加载完成时确定。
(jdk1.8中,运行时常量池、类常量池存在于方法区中。)

步骤 2、 为对象分配内存空间

JVM为对象分配空间,即把一块确定大小的内存块从Java堆中划分出来。

1、指针碰撞

假设Java堆中内存是绝对规整的,所有被使用过的内存都被放在一边,空闲的内存被放在另一边,中间放着一个指针作为分界点的指示器,那所分配内存就仅仅是把那个指针向空闲空间方向挪动一段与对象大小相等的距离。

正常状态:
在这里插入图片描述
为对象分配内存:
在这里插入图片描述

这种方式的优点是工作简单,效率高,只需要移动指针就可以分配内存空间。

缺点也很明显:由于用指针碰撞分配内存空间分为两步,1、读取指针当前的位置 2、根据自身大小移动指针,不是原子操作,对象创建在虚拟机中是非常频繁的操作,在并发情况下,会导致执行读操作或执行写操作的结果与预设的结果不一致(指针划分不一致)。
例如:线程A要给对象分配8kb,读取到指针当前的位置,时间片用完,切换到线程B,线程B要给它的对象分配16kb,也读取到指针当前的位置(和线程A读取到的一样),将指针向空闲内存方向移动16kb大小,线程B时间片用完,切换到线程A继续执行,由于线程A使用的指针位置还是之前读到的。(线程不安全问题)

针对指针碰撞线程不安全,有两种方案:

  1. 同步处理(加锁)分配内存空间行为

采用 CAS 分配重试的方式来保证更新操作的原子性

  1. 把内存分配行为按照线程,划分在不同的内存空间进行
  1. 即每个线程在Java堆中预先分配一小块内存,称为本地线程分配缓冲(Thread Local Allocation Buffer,TLAB),哪个线程要分配内存,就在哪个线程的本地缓冲区中分配,只有本地缓冲区用完
    了,分配新的缓存区时才需要同步锁定
  2. 虚拟机是否使用TLAB,可以通过-XX:+/-UseTLAB参数来
    设定。

2、空闲列表

如果Java堆中的内存并不是规整的, 已被使用的内存和空闲的内存相互交错在一起,那就没有办法简单地进行指针碰撞了,虚拟机就必须维护一个列表,记录上哪些内存块是可用的,在分配的时候从列表中找到一块足够大的空间划分给对象实例,并更新列表上的记录。

选择哪种分配方式

两种方式的选择由 Java 堆是否规整决定,Java 堆是否规整是由选择的垃圾收集器是否具有压缩整理能力决定的。

步骤3、将内存空间初始化为零值

内存分配完成之后,虚拟机必须将分配到的内存空间(但不包括对象头)都初始化为零值。零值初始化意思就是对对象的字段赋0值,或者null值,这也就解释了为什么这些字段在不需要进程初始化时候就能直接使用。
如果使用了TLAB的话,这一项工作也可以提前至TLAB分配时顺便进行。

步骤4、对对象进行必要的设置

例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的GC分代年龄等信息。这些信息存放在对象的对象头中。

从虚拟机的视角来看,一个新的对象已经产生了。但是从Java程序的视角看来,对象创建才刚刚开始——构造函数,即Class文件中的()方法还没有执行,所有的字段都为默认的零值,对象需要的其他资源和状态信息也还没有按照预定的意图构造好。

步骤5、执行实例的初始化方法init

init方法包含成员变量、构造代码块的初始化,按照声明的顺序执行,执行对象的构造
方法,并把堆内对象的首地址赋值给引用变量。至此,对象创建成功。

总结

在这里插入图片描述

注意

并发情况下,需要考虑操作的步骤是不是原子性,如果不是,就要加锁。原子性就是动作不能再继续被拆分了,读是原子性,写也是原子性,但是读+写就不是原子性

相关文章:

【JVM】详解对象的创建过程

文章目录 1、创建对像的几种方式1、new关键字2、反射3、clone4、反序列化 2、创建过程步骤 1、检查类是否已经被加载步骤 2、 为对象分配内存空间1、指针碰撞针对指针碰撞线程不安全,有两种方案: 2、空闲列表选择哪种分配方式 步骤3、将内存空间初始化为…...

华纳云:ubuntu下如何搭建nfs服务

在Ubuntu下搭建NFS(Network File System)服务,可以实现网络文件共享。以下是在Ubuntu上搭建NFS服务的步骤: 安装NFS服务器和客户端软件: 打开终端,并使用以下命令安装NFS服务器和客户端软件: sudo apt-get update s…...

HCIA实验二

实验要求: 1.R2为ISP,只能配置IP 2.R1-R2之间为HDLC封装 3.R2-R3之间为PPP封装,pap认证,R2为主认证方 4.R2-R4之间为PPP封装,chap认证,R2为主认证方 5.R1、R2、R3构建MGRE,仅R1的IP地址固定…...

stm32 舵机 cubemx

文章目录 前言一、cubemx配置二、代码1.serve.c2.serve.h3.主函数 总结 前言 stm32对舵机进行控制,很简单直接一个pwm就可以实现 pwm的周期是50HZ占空比分别对应 一个0.5ms的高电平对应于0度 一个1.5ms的高电平对应于90度 一个2.5ms的高电平对应于180度 因此&#…...

无涯教程-jQuery - Spinner组件函数

Widget Spinner 函数可与JqueryUI中的窗口小部件一起使用。Spinner提供了一种从一组中选择一个值的快速方法。 Spinner - 语法 $( "#menu" ).selectmenu(); Spinner - 示例 以下是显示Spinner用法的简单示例- <!doctype html> <html lang"en"…...

Python 有趣的模块之pynupt——通过pynput控制鼠标和键盘

Python 有趣的模块之pynupt ——通过pynput控制鼠标和键盘 文章目录 Python 有趣的模块之pynupt ——通过pynput控制鼠标和键盘1️⃣简介2️⃣鼠标控制与移动3️⃣键盘控制与输入4️⃣结语&#x1f4e2; 1️⃣简介 &#x1f680;&#x1f680;&#x1f680;学会控制鼠标和键盘是…...

docker基于centos7镜像安装python3.7.9

下载centos7镜像 docker pull centos&#xff1a;centos7 启动容器centos-python-3.7 docker run -itd --name centos-python-3.7 -p 60021:22 --privileged centos:centos7 /usr/sbin/init 进入容器 docker exec -it centos-python-3.7 /bin/bash centos7环境下安装python3.7.…...

JavaScript中的switch语句

switch语句和if语句一样&#xff0c;同样是运用于条件循环中&#xff1b; 下面例子我们用switch实现 例如如果今天是周一就学习HTML&#xff0c;周二学习CSS和JavaScript&#xff0c;周三学习vue&#xff0c;周四&#xff0c;周五学习node.js&#xff0c;周六周日快乐玩耍&…...

Jquery笔记

DOM对象通过jquery获取 所有的代码都是基于引入jquery.js文件 var mydiv $(#div);//直接获取到DOM对象元素id var mydiv$(.div)&#xff1b;//通过class获取DOM对象&#xff0c;如果有同名class只会获取第一个 var mysapn$(span);//通过元素的标签名获取DOM对象 var divarr$(…...

【C++】优先级队列的基本概念以及其模拟实现

文章目录 补充知识&#xff1a;仿函数一、优先级队列&#xff1a;1.引入2.介绍 二、priority_queue的模拟实现1.大体框架2.私有成员函数&#xff1a;1.向下调整&#xff08;AdjustDown&#xff09;2.向上调整&#xff08;AdjustUp&#xff09; 3.公有成员函数1大小&#xff08;…...

TextClamp for Vue3.0(Vue3.0的文本展开收起组件)

呦&#xff01;大家好&#xff0c;好久没有更新博客了&#xff0c;最近实现了一个一直想自己完成的一个东西&#xff0c;就是文本的展开收起组件&#xff0c;以前项目需要用到&#xff0c;自己实现一个又太繁琐&#xff0c;所以那个时候都是用的别人的轮子&#xff0c;现在自己…...

区间预测 | MATLAB实现VAR向量自回归时间序列区间预测

区间预测 | MATLAB实现VAR向量自回归时间序列区间预测 目录 区间预测 | MATLAB实现VAR向量自回归时间序列区间预测预测效果基本介绍程序设计参考资料预测效果 基本介绍 区间预测 | MATLAB实现VAR向量自回归时间序列区间预测 VAR(Vector Autoregression)模型是一种广泛应用于时…...

在 Windows 上搭建 NTP 服务器

文章目录 一、基础环境二、适用场景三、操作步骤四、常用的NTP服务器五、参考资料 版权声明&#xff1a;本文为博主原创文章&#xff0c;于2023年7月30日首发于CSDN&#xff0c;转载请附上原文出处链接和本声明。本文链接&#xff1a;https://blog.csdn.net/u011046671 一、基础…...

应急响应经典案例-FTP 暴力破解

应急响应经典案例-FTP 暴力破解 应急场景日志分析应急处理措施 应急场景 从昨天开始&#xff0c;网站响应速度变得缓慢&#xff0c;网站服务器登录上去非常卡&#xff0c;重启服务器就能保证一段时间的正常访问&#xff0c;网站响应状态时而飞快时而缓慢&#xff0c;多数时间是…...

41. linux通过yum安装postgresql

文章目录 1.下载安装包2.关闭内置PostgreSQL模块:3.安装postgresql服务:4.初始化postgresql数据库:5.设置开机自启动:6.启动postgresql数据库7.查看postgresql进程8.通过netstat命令或者lsof 监听默认端口54329.使用find命令查找了一下postgresql.conf的配置位置10.修改postgre…...

SpringBoot启动流程及自动配置

SpringBoot启动流程源码&#xff1a; 1、启动SpringBoot启动类SpringbootdemoApplication中的main方法。 SpringBootApplication public class SpringbootdemoApplication {public static void main(String[] args) {SpringApplication.run(SpringbootdemoApplication.class, …...

【Linux】进程轻松入门

目录 一&#xff0c; 冯* 诺依曼体系结构 1&#xff0c;存储结构 ​编辑 二&#xff0c; 操作系统 1&#xff0c;概念 2&#xff0c;设计OS的目的 3&#xff0c;定位 4&#xff0c;如何理解 "管理" 5&#xff0c; 总结 三&#xff0c;进程 1. 概念 那么…...

【使用时空RBF-NN进行非线性系统识别】实现了 RBF、分数 RBF 和时空 RBF 神经网络,用于非线性系统识别研究(Matlab代码实现)

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

Tomcat 安装配置教程及成功后,启动失败报错解决方案

解决方案 我的报错原因是因为我的JDK是1.8的而我的Tomcat是10版本的&#xff0c;可能是因为版本原因吧&#xff0c;我重新装了Tomcat 9就可以启动成功了&#xff01; 简单说下安装的时候需要注意哪些步骤吧 今天我在安装tomcat10的时候&#xff0c;安装成功后&#xff0c;启…...

C#文件操作从入门到精通(2)——查看某个dll中有哪些函数

kernel32.dll中含有ini文件操作使用的函数,我们可以通过VisualStudio自带的dumpbin.exe查看dll所包含的函数,操作步骤如下: 1、找到dumpbin.exe所在的文件夹 我的电脑中安装了VisualStudio2019社区版以及VisualStudio2017Professional,但是我发现VisualStudio2019社区版中…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言&#xff1a;多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时&#xff0c;​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套&#xff1a;跨云网络构建数据…...

python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)

更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...

什么是EULA和DPA

文章目录 EULA&#xff08;End User License Agreement&#xff09;DPA&#xff08;Data Protection Agreement&#xff09;一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA&#xff08;End User License Agreement&#xff09; 定义&#xff1a; EULA即…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

是否存在路径(FIFOBB算法)

题目描述 一个具有 n 个顶点e条边的无向图&#xff0c;该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序&#xff0c;确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数&#xff0c;分别表示n 和 e 的值&#xff08;1…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码

目录 一、&#x1f468;‍&#x1f393;网站题目 二、✍️网站描述 三、&#x1f4da;网站介绍 四、&#x1f310;网站效果 五、&#x1fa93; 代码实现 &#x1f9f1;HTML 六、&#x1f947; 如何让学习不再盲目 七、&#x1f381;更多干货 一、&#x1f468;‍&#x1f…...

QT3D学习笔记——圆台、圆锥

类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体&#xff08;对象或容器&#xff09;QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质&#xff08;定义颜色、反光等&#xff09;QFirstPersonC…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)

考察一般的三次多项式&#xff0c;以r为参数&#xff1a; p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]&#xff1b; 此多项式的根为&#xff1a; 尽管看起来这个多项式是特殊的&#xff0c;其实一般的三次多项式都是可以通过线性变换化为这个形式…...

解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist

现象&#xff1a; android studio报错&#xff1a; [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决&#xff1a; 不要动CMakeLists.…...