变量类型及其在jvm中的存储

本文探讨了Java中数据类型在JVM中的存储方式,包括栈、堆和方法区的原理。通过实例分析了基本数据类型与引用类型的存储区别,如Integer的常量池优化和字符串常量的共享。并介绍了成员变量与局部变量的存储差异,以及自动拆箱装箱的过程。此外,还涉及到了面试中常见的String对象创建问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

最近实习生招聘面试,喜欢问jvm的存储结构,这个大家基本都能回答出来(八股文背诵的嫌疑),但是问了几个具体的case,就很多同学都回答不出来或者很模糊。
所以同学们真的了解数据类型在jvm中的存储么?
 

举例如下:

int a1 = 1;
Integer a2 = 1;

Integer a3 = 128;
Integer a4 = 128;

System.out.println(a1==a2);
System.out.println(a3==a4);

String s1 = "china";
String s2 = new String("china");  

 

一、基础知识

1.1、变量的分类

成员变量:定义在类中方法(代码块)外的变量。
使用static修饰的成员变量: 静态成员变量位于方法区中(详细请看下文),是类级别的。
未使用static修饰的成员变量:实例成员变量位于堆空间中(详细请看下文),是对象级别的。

局部变量 :除成员变量外都是局部变量位于方法所在的栈帧中(详细请看下文),是方法级别的。

1.2、JVM的存储结构
栈:位于通用RAM(随机访问存储器),方法执行时创建方法栈帧,存放基本数据类型的变量数据和对象的引用。但对象本身不存放在栈中,而是存放在堆(new出来的对象)或者常量池中(字符串常量对象存放在常量池中)
堆:存放所有new出来的对象
静态域(方法区):存放静态成员(static定义的)
常量池(方法区):存放字符串常量、基本类型常量(public static final)

 

二、局部变量

2.1、基本数据类型
在方法调用时执行到该变量的初始化语句时,直接将该变量的值保存到该方法的栈帧中。
int a1 = 1;

 


2.2、引用类型

  • 在方法调用时,将引用的堆内存中的值的地址保存到该变量到的栈内存中。
  • 对于基本类型的包装类型(符合常量池区间)和String,保存在方法区的常量池。

note:变量名称存储在栈中,变量的值存储要么在常量池,要么在堆中。

Integer a2 = 1; //1存储在常量池

Integer a3 = 128; //128由于超过了常量池的范围,相当于new Integer(128), 存储在堆中
Integer a4 = 128;

String s1 = "china"; //存储在常量池

这里有个经典的面试题:String ss1 = new String("china");会创建几个对象?
答案是1-2个。如果产量池中有"china",则创建1个,否则会在堆中创建1个,常量池中创建1个。


自动拆箱装箱

这里还有个神奇的现象:

System.out.println(a1==a2); //true
System.out.println(a3==a4); //false

==比较的两边是基本数据类型和包装类型,进行值的比较(而不是比较对象地址)。
原因是:会进行自动拆箱装箱

 

三、成员变量

实例成员变量:参考上面。大多数在堆内存中的值,基本数据类型有可能在常量池。

静态成员变量(类成员变量):值存在方法区的内存空间中。——方法区除了有常量池,还有静态区。

<think>好的,我现在需要帮助用户了解Linux环境下的交叉编译链接过程或解决相关问题。首先,我得回忆一下交叉编译的基本概念,确保自己理解正确。根据用户提供的引用内容,交叉编译是在一个平台上生成另一个平台的可执行代码,比如在Ubuntu上编译运行在树莓派的程序。用户可能遇到了链接错误,需要教程或解决方法。 用户的问题主要集中在链接过程,这可能涉及到路径、符号缺失、工具链配置等。我需要分步骤解释链接过程,并给出常见错误及解决方法。根据引用[1],--with-sysroot参数很重要,它指定了交叉编译时的系统根目录,链接器会在这里查找和头文件。如果未正确设置,可能会导致找不到的错误。引用[3]提到openssl交叉编译时需要修改CROSS_COMPILE和相关工具路径,这也涉及到链接时使用的工具是否正确。 接下来,我应该先概述交叉编译链接流程,包括编译链接步骤,强调工具链和sysroot的作用。然后,列举常见错误,比如找不到、符号错误、架构不匹配,并给出具体解决方法,比如检查工具链路径、设置环境变量如CC、LDLDFLAGS等。此外,可能需要提到如何验证交叉编译是否正确,使用file或readelf命令。 还要注意用户可能混淆了主机和目标平台的路径,导致链接器使用了错误的。例如,交叉编译时如果没有指定--sysroot,链接器可能会默认使用主机的/usr/lib,而不是目标平台的,这会导致不兼容。需要指导用户正确配置sysroot,并确保所有依赖都已交叉编译并安装到sysroot中。 最后,生成相关问题,帮助用户进一步学习,比如如何配置交叉编译环境,解决加载问题,或优化编译选项。需要确保回答结构清晰,步骤详细,并引用提供的资料来支持建议,比如引用[1]和[3]中关于sysroot和工具链配置的部分。</think>### Linux交叉编译链接过程解析 交叉编译链接过程需要特殊处理目标平台与主机平台的架构差异,以下是关键步骤和常见问题解决方案: 1. **工具链配置** - 必须使用目标平台对应的链接器(如`arm-linux-gnueabihf-ld`) - 设置环境变量: ```bash export CC=arm-linux-gnueabihf-gcc export LD=arm-linux-gnueabihf-ld export LDFLAGS="-L/path/to/target/lib" ``` 2. **Sysroot系统根目录** 使用`--sysroot`指定目标平台路径: ```bash ./configure --host=arm-linux-gnueabihf --with-sysroot=/opt/arm-sysroot ``` 这会强制链接器在指定目录下搜索文件,避免误用主机[^1] 3. **典型链接错误解决方案** | 错误类型 | 现象示例 | 解决方法 | |---------|----------|---------| | 缺失 | `cannot find -lssl` | 确认交叉编译的openssl已安装到sysroot | | 符号未定义 | `undefined reference to 'SSL_new'` | 检查链接顺序,确保依赖在后 | | 架构不匹配 | `file format not recognized` | 使用`file`命令验证目标文件架构 | 4. **特殊处理** 编译时需指定运行时路径: ```bash -Wl,-rpath-link=/opt/arm-sysroot/usr/lib ``` 避免出现`No such file or directory`的运行时错误[^3] 5. **验证链接结果** ```bash arm-linux-gnueabihf-readelf -d target_bin | grep NEEDED file target_bin ``` ### 常见错误排查流程 1. 检查工具链前缀是否正确 2. 验证sysroot目录是否包含目标架构的文件 3. 使用`-v`参数查看详细链接过程 4. 确认所有依赖都已完成交叉编译
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值