Java值传递机制本质是JVM在方法调用时将参数值(基本类型值或引用地址)复制到新栈帧的局部变量表中,字节码指令(如iload/istore)、JVM规范明确要求“by value”、HotSpot源码注释证实为内存地址的逐字节拷贝。

Java 中的值传递机制,不能靠背结论,得看它在字节码和 JVM 运行时里“真正在做什么”。源码分析不是指翻 JDK 源码(比如 Object 类),而是聚焦三类可验证材料:反编译后的字节码(javap -c)、JVM 规范中关于方法调用的定义、以及 HotSpot 虚拟机关键操作的注释级说明。下面从三个实操角度展开:
看字节码:形参赋值本质就是栈帧压入副本
以基本类型为例:
public static void change(int x) { x = 100; }
反编译后关键指令是:
- iload_1:把局部变量表索引 1 的 int 值(即传入的副本)加载到操作数栈
- sipush 100 → istore_1:把 100 存回同一个局部变量槽(覆盖副本)
注意:没有指令去读或写调用方栈帧里的原始变量。形参 x 在被调用方法的栈帧中是独立槽位,初始化动作(如 iload_0 加载实参值再 istore_1)本身就是一次显式拷贝。
你是 TypeScript 项目架构专家,专注于脚手架搭建生产就绪的 Node.js 和前端应用。生成包含现代工具链(pnpm、Vite、Next.js)、类型
查 JVM 规范:方法调用明确要求“值的复制”
《JVM Specification》第 6 版 §5.4.3.3 和 §6.5 “invokestatic” 指令定义中明确写道:
- “The arguments are passed by value: each argument value is copied into the local variable array of the new frame.”(参数按值传递:每个参数值被复制到新栈帧的局部变量数组中)
- 对引用类型,规范原文用词是 “a reference to an object” —— 但紧接着强调 “the reference itself is passed by value”,即“引用本身”被复制,而非对象或引用变量的绑定关系
这意味着:JVM 层面不区分“基本类型值”和“引用类型的地址值”,统一视为“能放进局部变量槽的 32/64 位数据”,全部走同一套复制逻辑。
读 HotSpot 关键注释:解释器如何处理引用参数
在 OpenJDK 源码 src/hotspot/share/interpreter/interpreterRuntime.cpp 中,InterpreterRuntime::slow_signature_handler 函数负责把调用方栈帧中的参数搬运到被调用方栈帧。其注释直白指出:
- “Copy parameters from caller’s expression stack to callee’s locals”(将参数从调用方操作数栈复制到被调用方局部变量)
- 对对象引用,代码实际执行的是
*(oop*)to_addr = *(oop*)from_addr—— 即内存地址值的逐字节拷贝,不是指针重绑定
这个动作发生在每次方法入口,与参数类型无关。所谓“对象可被修改”,只是因为两个栈帧里的地址副本指向了堆中同一块内存区域,而非 JVM 对引用类型开了后门。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










