Linux基础IO【软硬链接与动静态库】

news2024/11/16 2:30:45

✨个人主页: 北 海
🎉所属专栏: Linux学习之旅
🎃操作环境: CentOS 7.6 阿里云远程服务器

成就一亿技术人


文章目录

  • 🌇前言
  • 🏙️正文
    • 1、软硬链接
      • 1.1、基本认知
      • 1.2、实现原理
      • 1.3、应用场景
      • 1.4、取消链接
      • 1.5、ACM时间
    • 2、动静态库
      • 2.1、认识库
      • 2.2、库的作用
    • 3、制作静态库
      • 3.1、静态库的打包
      • 3.2、静态库的使用
    • 4、制作动态库
      • 4.1、动态库的打包
      • 4.2、动态库的链接与使用
      • 4.3、动态库的链接原理
    • 5、动态库知识补充
  • 🌆总结


🌇前言

假设你下载了一款游戏,你是否会跑到游戏所在目录中双击 .exe 打开游戏?答案是不会,大多数人都会通过桌面的快捷方式直接打开文件,而这个快捷方式实际就是对 .exe软链接 文件;当你在游戏中加载地图、道具等资源时,这些数据是存在 .exe 文件中的吗?答案是当然不是,这些资源文件都以 的方式与 .exe 位于同一目录中,通常为动态库,在 Windows 中后缀为 dll,那么这些神奇的辅助文件是如何产生的?本文将带你一起揭晓

举例


🏙️正文

学习软硬链接前,需要先对文件系统有一个系统性的认识,其中的 inode 至关重要,还未学习的同学可以先看看这篇文章:《Linux基础IO【深入理解文件系统】》

1、软硬链接

1.1、基本认知

对文件进行软硬链接非常简单,只需要通过 ln -sln 对文件进行链接即可,生成的链接文件类型为 l(普通文件为 -,目录文件为 d

对文件 myproc 进行软链接,生成软链接文件 my-sort,其中软链接文件名可以自定义

ln -s myproc my-sort

软链接

生成硬链接文件就更简单了,对文件 myproc 进行硬连接,生成硬连接文件 my-hard,其中硬链接文件名也可以自定义

ln myproc my-hard

图解

注意: 可以对目录进行软链接,但不能对目录进行硬链接,具体原因后面再解释

生成的软硬链接文件如何使用呢?

  • 像源文件一样使用即可,结果一模一样(因为当前软硬链接的都是同一个源文件)

结果

虽然此时的软硬链接执行结果一致,但这两种链接方式在本质上有很大区别

  • 软链接文件的 inode 编号与源文件不同(独立存在),软连接文件比源文件小得多,并且 软连接文件->源文件
  • 硬链接文件与源文件共用一个 inode 编号(对源文件其别名),硬链接文件与源文件一样大,并且硬链接文件与源文件的链接数变成了 2

图解

软链接文件依赖于源文件,而硬链接文件是源文件的别名

当我们将源文件删除后,软连接失效;硬链接仍然有效,不过硬链接数变为了 1

图解
同样是对源文件进行链接,为何两种链接方式差别如此大呢?这就不得不谈一下它们的实现原理了

1.2、实现原理

软链接又称为符号链接,它是一个单独存在的文件,拥有属于自己的 inode 属性及相应的文件内容,不过在软连接的 Data block 中存放的是源文件的地址,因此软连接很小,并且非常依赖于源文件

图解
因此如果源文件被删除了,那么在执行软连接文件时,其中的地址就是一个无效地址(目标文件已丢失),此时就会报错 No such file or directory

假设只是单纯的删除软连接文件,那么对源文件的内容没有丝毫影响,就好比 Windows 桌面上的快捷方式,有的人以为将快捷方式(软链接)文件删除了,就是在 “卸载” 软件,其实不是,如果想卸载软件,直接将其源文件相关文件夹全部删除即可

硬链接并非创建一个相同的文件进行链接,而是在源文件所目录下的 【inode编号 与文件名对应表中】,新增 【inode 编号与硬链接文件名】的映射关系,并将 inode 结构体中的引用计数 +1,表示当前已成功硬链接上了一个文件

图解
当删除当前 inode 对应文件时,会 先判断 ref_count 是否为 1,如果是,才会将文件内容及其属性真正删除,否则删除的只是 文件名inode 编号的映射关系

这也就解释了为什么删除源文件后,硬链接文件不受任何影响,仅仅只是 硬链接数 - 1,同理,删除硬链接文件,也不会影响源文件

为什么新建目录的硬链接数为 2

  • 因为一个目录在新建后,其中默认存在两个隐藏文件:...
  • 其中 . 表示当前目录,.. 表示上级目录

Linux 中的目录结构为多叉树,即当前节点(目录)需要与父节点(上级目录)、子节点(下级目录)建立链接关系,并且还得知道当目录的地址,否则就会导致切换目录时出现错误

图解

为了避免因用户的误操作而导致的目录环状问题,规定用户不能手动给目录建立硬链接关系,只能由 OS 自动建立硬链接,比如新目录后,默认与上级目录和当前目录建立硬链接文件,在当目录下创建新目录后,当前目录的硬链接数 + 1

图解
小技巧:将目录的硬链接数 - 2,就可以知道该目录中有多少个目录了

ls -d	//只查看目录文件

图解

1.3、应用场景

软链接可以当作快捷方式使用,比如快速运行一个藏的很深的可执行程序

图解

而硬链接一是可以用来当作目录移动的工具,二是可以用来给重要的源文件起别名并使用,一旦发生删除等不可逆行为时,可以确保源文件的安全

注意: 硬链接并不是将源文件直接进行备份,而是新建立 inode 编号与硬链接文件名的映射关系,同时 struct inode 中的引用计数 ref_count++,只有当 ref_count == 1 时才会真正删除文件内容及属性,否则都只是在取消映射关系和 ref_count--

1.4、取消链接

取消链接的方式有两种:

  • 直接删除链接文件
  • 通过 unlink 取消链接关系

图解

1.5、ACM时间

每一个文件都有三个时间:访问 Access、修改属性 Change、修改内容 Modify,简称为 ACM 时间

可以通过 stat 查看指定文件的 ACM 时间信息

ACM
这三个时间的刷新策略如下:

  • Access:最近一次查看内容的时间,具体实现取决于系统
  • Change:最近一次修改属性的时间
  • Modify:最近一次修改内容的时间(内容更改后,属性也会跟着修改)

Access 是高频操作,如果每次查看都更新的花,会导致 IO 效率变低,因此 实际变化取决于刷新策略:查看 N 后次刷新

注意: 修改内容一定会导致属性时间被修改,但不一定会导致访问时间被修改,因为可以不打开文件,对文件进行操作


2、动静态库

接下来学习动静态库的相关内容,了解程序运行时是如何调用资源的

2.1、认识库

常见的库文件:stdio.hstdlib.hstring.h

库分为 动态库静态库

  • Linux 中,.a 后缀为静态库,.so 后缀为动态库
  • Windows 中,.lib 后缀为静态库,.dll 后缀为动态库
  • 虽然不同环境下的后缀有所不同,但其工作原理是一致的

库命名

  • 比如 libstdc++.so.6

  • 去掉前缀跟后缀,最终库名为 stdc++

查看当前环境中的库文件

find /usr/lib64/libc*

结果

C++ 中具体库文件可以这样查看

find /usr/lib64/libstdc*

结果

无论是 C语言 还是 C++,在编写程序时,一定离不开库文件,比如之前模拟实现的 FILE 类型,就位于 stdio.h 这个库中,动态库优势比静态库明显,因此在编译代码时,默认采用动态链接的方式,如果想指定为静态链接编译,只需要在 gcc/g++ 语句后面加上 -static 即可(前提是得有静态库)

一般云服务默认只会存在动态库,静态库需要单独安装

图解

关于动静态库的优缺点可以看看下面这个表格

区别动态库静态库
调用方式通过函数位置进行调用直接将需要的函数拷贝至程序中
依赖性(运行时)需要依赖于动态库可以独立于静态库运行
空间占用共享动态库中的代码,空间占用少拷贝代码会占用大量空间
加载速度调用函数,加载速度慢直接运行,加载速度快

注意: 静态库是将所需要的函数代码拷贝到源文件中直接使用,而动态库是通过动态链接的方式,进行函数链接使用

2.2、库的作用

所以,库文件到底有什么用?

  • 提高开发效率

系统已经预装了 C/C++ 的头文件和库文件,头文件提供说明,库文件提供方法的实现

  • 头和库是有对应关系的,需要组合使用
  • 头文件在预处理阶段就已经引入了,链接的本质就是在链接库

简言之,如果没有库文件,那么你在开发时,需要自己手动将 printf 等高频函数编写出来,因此库文件可以提高我们的开发效率,比如 Python 中就有很多现成的库函数可以使用,效率很高

语法提示是如何做到的?

  1. 安装开发环境

    • 实际上是在安装编译器、开发语言配套的库和头文件
  2. 编译器的 语法提示功能来源于头文件(语法提示其实就是搜索)

  3. 我们在写代码时,开发环境是怎么知道语法错误或其他错误的?

    • 编译器有命令行模式,还有其他自动化模式,编写代码时,不断进行主动编译,排查错误

3、制作静态库

现在有一些简单的计算 demo 函数,能满足整型的 +- 计算,将这些代码作为库进行打包

myadd.h

#pragma once

//声明功能
int add(int x, int y);

myadd.c

#include "myadd.h"

//定义功能
int add(int x, int y)
{
    return x + y;
}

mysub.h

#pragma once

//声明功能
int sub(int x, int y);

mysub.c

#include "mysub.h"

//定义功能
int sub(int x, int y)
{
    return x - y;
}

主函数中将对这些自定义的库函数进行调用

test.c

#include <stdio.h>
#include "myadd.h"
#include "mysub.h"

int main()
{
    printf("2 + 3 = %d\n", add(2, 3));
    printf("18 - 6 = %d\n", sub(18, 6));
    return 0;
}

3.1、静态库的打包

静态库的打包主要分为以下两步:

  1. 将源文件进行 预处理->编译->汇编,生成可链接的二进制 .o 文件
  2. 通过指令将 .o 文件打包为静态库

将文件编译为 .o 二进制文件

gcc -c myadd.c mysub.c

结果

将所有的 .o 文件打包为一个静态库(库名自定义)

其中的 mycalc 为库名

ar -rc libmycalc.a *.o

结果

arGNU 提供的归档工具,常用来将目标文件打包为静态库
我们还可以使用 ar 反向查看静态库中的具体文件
ar -tv 静态库文件
结果

获得静态库后,就可以进行使用了

注:此时的 .h.c.o 文件位于 myinclude 文件夹中,而静态库文件 .a 位于 mylib 文件夹中

3.2、静态库的使用

方法一:通过指定路径使用静态库

如果直接编译程序,会出现编译失败的情况,因为编译器不认识第三方库(需要提供第三方库的路径及库名)

结果

第一方库:语言提供
第二方库:操作系统提供
第三方库:other 提供的库,比如当前我们直接打包的静态库

对于自己写的的第三库的使用,需要标注三个参数:

  1. -I 所需头文件的路径 需要将所需头文件的路径加上,此处为 ./myinclude
  2. -L 所需库文件的路径 这里加的是库文件的路径,也为 ./mylib
  3. -l 待链接静态库名 所需要链接的静态库名字,这里为 mycalc

将选项加上后重新编译

gcc -o myproc test.c -I./myinclude -L./mylib -lmycalc

j结果

为什么编译 C/C++ 代码时,不需要指定路径?

  • 因为这些库都是系统级的,gcc/g++ 默认找的就是 stdc/stdc++

方法二:将头文件和静态库文件安装至系统目录中

除了这种比较麻烦的指定路径编译外,我们还可以将头文件与动态库文件直接安装在系统目录中,直接使用,无需指定路径(需要指定静态库名)

所谓的安装软件,就是将自己的文件安装到系统目录下

sudo cp ./myinclude/*.h /usr/include/
sudo cp ./mylib/*.a /lib64/

结果

注意: 将自己写的文件安装到系统目录下是一件危险的事(导致系统环境被污染),用完后记得手动删除

结果


4、制作动态库

除了可以制作静态库外,我们还可以制作动态库,这里用的例子和上面一样

4.1、动态库的打包

动态库不同于静态库,动态库中的函数代码不需要加载到源文件中,而是通过 与位置无关码 ,对指定函数进行链接使用

动态库的打包也同样分为两步:

  1. 编译源文件,生成二进制可链接文件,此时需要加上 -fPIC 与位置无关码
  2. 通过 gcc/g++ 直接目标程序(此时不需要使用 ar 归档工具)

将源文件编译为 .o 二进制文件,此时需要带上 fPIC 与位置无关码

gcc -c -fPIC *.c

结果

将所有的 .o 文件打包为动态库(借助 gcc/g++

gcc -o libmycalc.so *.o -shared

结果
获得静态库后,就可以进行使用了

注:此时的 .h.c.o 文件位于 myinclude 文件夹中,而动态库文件 .so 位于 mylib 文件夹中

4.2、动态库的链接与使用

像使用静态库一样使用动态库(指定路径及库名),编译成功,但运行失败!

结果
为什么会出现这种问题?因为当前只告诉了编译器动态库的位置,没有告诉 OS

通过 ldd 查看程序链接情况:

结果

运行时,OS 是如何链接动态库?

  1. 环境变量 LD_LIBRARY_PATH (默认没有这个环境变量),将第三方动态库路径添加至此环境变量中(临时方案)
  2. sudo/lib64/ 目录下建立动态库的软链接
  3. 更改配置文件 /etc/ld.so.conf.d 这个目录中都是各种动态库配置文件,创建文件 xx.conf 至目录中(文件中存储的是第三方动态库的路径)ldconfig 令配置文件生效

以上三种方式都可以正常使用动态库,下面就来逐个进行尝试

方法一:通过环境变量解决

添加动态库路径至 LD_LIBRARY_PATH 环境变量中

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/Yohifo/linux/Explore/file/blog/Test_5_3/mylib

结果
环境变量 LD_LIBRARY_PATH 是程序在进行动态库查找时的默认搜索路径

注意: 更改环境变量只是临时方案,重新登录后会失效

方法二:将动态库的软链接文件存入系统目录中

sudo ln -s /home/Yohifo/linux/Explore/file/blog/Test_5_3/mylib/libmycalc.so /lib64/libmycalc.s

图示
注意: 创建软连接文件时,需要使用绝对路径!

方法三:更改配置文件中的信息

echo /home/Yohifo/linux/Explore/file/blog/Test_5_3/mylib > Yohifo.conf
sudo mv Yohifo.conf /etc/ld.so.conf.d/
sudo ldconfig

图示

注意: 后两种方法都可以做到永久生效(因为存入了系统目录中),但在使用完后最好删除,避免污染系统环境

4.3、动态库的链接原理

程序在链接动态库函数时,是通过 动态库起始地址 + 所链接函数偏移量 的方式进行链接访问的,而这个偏移量就是 fPIC 与位置无关码

地址其实就两种:绝对地址和相对地址,静态链接时,将可链接的二进制文件加载至程序中,直接通过 绝对地址 进行链接,假设函数被调用了多次,就会导致代码冗余等问题;动态链接采用 相对地址 的方式进行链接,同一个函数的 动态库起始地址 + 所链接函数偏移量 值相同,代码只需要加载一份,并且可以任意位置进行函数调用(与位置无关)

图示

动态库中所有地址都是偏移量,默认从 0 开始

只有当一个库被真正映射进地址空间后,它的起始地址才能真正确定

  • 链接库中的函数时,通过 动态库的起始地址 + 函数偏移量 的方式链接函数
  • 这种方法不论在什么位置,都可以随便链接函数(与位置无关)
  • 与位置无关码:动态库中地址,是偏移量

5、动态库知识补充

当同时拥有 静态库 和 动态库 时,默认采用动态链接

结果

如何指定生成静态链接文件?

结果

如果只有静态库,但又不指定静态链接,会发生什么?

结果

可以看看以上三种方式生成的可执行程序大小:

结果
静态链接生成的程序比动态链接大得多,并且内含静态库的动态链接程序,也比纯粹的动态链接程序大,说明程序不是 非静即动,可以同时使用动态库与静态库


🌆总结

以上就是本次关于 Linux基础IO【软硬链接与动静态库】的全部内容了,本文主要围绕 软硬链接动静态库 展开,详细说明了 软硬链接 的链接方法、区别及实现原理;之后还学习了 动静态库 相关内容,学会了 动静态库 的打包制作,最后简单了解了 动态库 的链接原理,我们可以利用已学知识对 myStdio 进行打包,分享给其他人使用


星辰大海

相关文章推荐

Linux基础IO【深入理解文件系统】

Linux【模拟实现C语言文件流】

Linux基础IO【重定向及缓冲区理解】

Linux基础IO【文件理解与操作】

===============

Linux【模拟实现简易版bash】

Linux进程控制【进程程序替换】

Linux进程控制【创建、终止、等待】

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaWeb ( 一 ) HTTP协议

1.http协议 1.0.Web Web指的是World Wide Web&#xff0c;也称为万维网&#xff0c;是一种基于互联网的信息系统&#xff0c;由全球数百万个网站组成。它允许用户通过使用网页浏览器访问和交互信息&#xff0c;例如阅读新闻、购物、发送和接收电子邮件、社交媒体等。 Web使用…

解密.[support2022@cock.li].faust后缀勒索病毒加密的文件:拯救您的企业数据的完整指南!

引言&#xff1a; 您的企业数据是您业务的核心。但是&#xff0c;当.[support2022cock.li].faust后缀勒索病毒突袭您的系统时&#xff0c;您的数据将遭受沉重打击。这种恶意软件利用高级加密算法&#xff0c;将您的文件锁定在无法访问的状态。在这篇详细的指南中&#xff0c;9…

tcp/ip

这里写自定义目录标题 线程 防止阻塞 123 windows下4 https://zhuanlan.zhihu.com/p/139454200 https://www.bilibili.com/video/BV1eg411G7pW/?spm_id_from333.337.search-card.all.click&vd_sourcee7d12c9f66ab8294c87125a95510dac9 with socket.socket() as s:s.bind(…

xcode Swift Log CocoaLumberjack

参考【iOS】CocoaLumberJack日志库集成 - 简书 logging - How to capture Device Logs in iOS during Runtime into a file in Documents Directory from iPhone? - Stack Overflow GitHub - apple/swift-log: A Logging API for Swift 如何导出日志 方法一发邮件&#xf…

Vue——Elementui案例实现

需求分析: 对于上面要仿照的页面先新建一个页面组件EmpView.vue组件在views文件夹下 基本页面布局 对于上面页面的布局其实在Element当中也可以找到相应可以实现的组件, 成功找到一个符合要求的布局&#xff0c;直接复制粘贴到项目里面 此时页面相应的位置已经有了对应的占位单…

自动化运维工具 Ansible

目录 Puppet 自动运维工具特点&#xff1a; Saltstack 自动运维工具特点&#xff1a; Ansible 自动运维工具特点: Ansible 运维工具原理 Ansible 管理工具安装配置 Ansible 工具参数详解 Ansible ping 模块实战 Ansible command 模块实战 Ansible copy 模块实战 Ansib…

uboot第二阶段 start_armboot函数代码分析

1.1、start_armboot函数简介 这个函数整个构成了uboot启动的第二阶段。 1.2、uboot第二阶段做的事情 uboot第一阶段主要就是初始化了SoC内部的一些部件&#xff08;譬如看门狗、时钟、串口…&#xff09;&#xff0c;然后初始化DDR并且完成重定位。那么&#xff0c;uboot的第…

数字化转型导师坚鹏:企业数字化营销能力提升

企业数字化营销能力提升 课程背景&#xff1a; 很多企业存在以下问题&#xff1a; 不清楚数字化营销对企业发展有什么影响&#xff1f; 不知道如何提升企业数字化营销能力&#xff1f; 不知道企业如何开展数字化营销工作&#xff1f; 课程特色&#xff1a; 原创企业数…

vcruntime140.dll无法继续执行代码?vcruntime140.dll如何修复?只需要3步即可

vcruntime140.dll是用于Microsoft Visual C Redistributable&#xff08;可再发行组件&#xff09;的一部分&#xff0c;它是一个动态链接库文件&#xff0c;包含了该软件包提供的运行库。在许多应用程序和游戏中&#xff0c;vcruntime140.dll文件经常被使用。如果该文件缺失或…

Tkinter正则表达式工具

文章目录 &#x1f3f3;️‍&#x1f308; 1. 导入tkinter和re模块&#x1f3f3;️‍&#x1f308; 2. 设置窗口居中&#x1f3f3;️‍&#x1f308; 3. 设置lable、text、button布局&#x1f3f3;️‍&#x1f308; 4. 设置下拉列表框&#x1f3f3;️‍&#x1f308; 5. 清空文…

Scrum敏捷开发和项目管理流程及工具

Scrum是全球运用最广泛的敏捷管理框架&#xff0c;Leangoo基于Scrum框架提供了一系列的流程和模板&#xff0c;可以帮助敏捷团队快速启动Scrum敏捷开发。 这里可以介绍一下在scrum中单团队敏捷开发如何管理&#xff0c;单团队敏捷开发主要是针对10-15人以下&#xff0c;只有一…

零基础如何学习挖漏洞?看这篇就够了【网络安全】

前言 有不少阅读过我文章的伙伴都知道&#xff0c;我从事网络安全行业已经好几年&#xff0c;积累了丰富的经验和技能。在这段时间里&#xff0c;我参与了多个实际项目的规划和实施&#xff0c;成功防范了各种网络攻击和漏洞利用&#xff0c;提高了安全防护水平。 也有很多小…

Qt常用快捷键

Qt常用快捷键 1.添加头文件&#xff1a;Alt Enter2.查看槽函数的实现 位置&#xff1a;F2 / F43.快速查看帮助文档&#xff1a;F14.代码快速对齐&#xff1a;Ctrl I5.代码全选&#xff1a;Ctrl A6.保存&#xff1a;Ctrl S7.代码复制&#xff1a;Ctrl C8.代码粘贴&#xff…

Flutter之插件开发plugin

目的:适用于独立业务模块,或者与原生页面交互频繁的地方。 基于flutter3.x , IDE :androidStudio 步骤: 1.新建flutter project 【New flutter project】. 2. 在新建工程面板记得切换 Project Type, 选择【PLugin】. 其他的根据足迹需求选择就行。 3. 在flutter主工…

联想凌拓教育行业解决方案

联想凌拓教育行业解决方案 教育部等六部门《关于推进教育新型基础设施建设构建高质量教育支撑体系的指导意见》&#xff0c;指出&#xff1a;信息网络、平台体系、数字资源、智慧校园、创新应用、可信安全的新型基础设施为六大发展重点&#xff0c;需建立全面覆盖的标准规范体…

文献集锦 | 非因生物空间多组学技术在头颈部肿瘤中的研究策略

头颈部鳞状细胞癌(HNSCC)是全球第七大癌症病因&#xff0c;是一种异质性恶性肿瘤&#xff0c;起源于上呼吸道&#xff0c;尤其是鳞状粘膜线。唇部、口腔和鼻腔、鼻窦、喉、鼻咽、口咽和下咽是HNSCC的受累部位。利用空间组学分析平台深入剖析组织肿瘤微环境&#xff0c;对深入理…

【大数据之Hadoop】从自定义 RPC 到 Hadoop RPC ,理解分布式通信系统的底层工作原理

1. 前言 Hadoop是分布式计算系统&#xff0c;在分布式环境中&#xff0c;网络通信模块是其核心模块之一。要学好Hadoop&#xff0c;需理解其底层通信系统的基本工作原理。Hadoop提供有体系完整的RPC框架&#xff0c;实现了对底层网络通信过程的优雅封装。 本文将从RPC概念说起…

从五一的旅游热潮看,该如何实现数字文旅的转型升级?

文旅产业是文化和旅游行业的融合&#xff0c;属于国家战略性产业&#xff0c;资源消耗低&#xff0c;带动系数大&#xff0c;就业机会多&#xff0c;综合效益好。改革开放以来&#xff0c;随着国内工业化、城镇化的快速发展&#xff0c;日益增长的大众化、多样化消费需求为文旅…

java电子招标采购系统源码:营造全面规范安全的电子招投标环境,促进招投标市场健康可持续发展

营造全面规范安全的电子招投标环境&#xff0c;促进招投标市场健康可持续发展 传统采购模式面临的挑战 一、立项管理 1、招标立项申请 功能点&#xff1a;招标类项目立项申请入口&#xff0c;用户可以保存为草稿&#xff0c;提交。 2、非招标立项申请 功能点&#xff1a;非招标…

JUC多并发编程 对象内存布局

对象的内存布局简介 在 Hotspot 虚拟机里&#xff0c;对象在堆内存中存在布局可划分为三个部分: 对象头(Header), 实例数据(Instance Data) 和对齐填充(Padding 保证8字节位数) 对象头 对象标记 MarkWord, 在64位操作系统中&#xff0c; Mark Word 占8个字节, 类型占 8个字节&…