Java在内存中是什么样子的
我是java新手,还在学习。我脑子里想的是内部和匿名类。现在我有一个关于java在内存中是什么样子的技术问题,当分配对象、定义类等时 比如,当我有一个字段是在外部类和内部类中定义的对象时,内存是什么样子的。静态类与非静态类看起来不同吗 我只需要一个视觉参考Java在内存中是什么样子的,java,memory,Java,Memory,我是java新手,还在学习。我脑子里想的是内部和匿名类。现在我有一个关于java在内存中是什么样子的技术问题,当分配对象、定义类等时 比如,当我有一个字段是在外部类和内部类中定义的对象时,内存是什么样子的。静态类与非静态类看起来不同吗 我只需要一个视觉参考 谢谢大家详细信息在实现中(而不是规范中)。然而,实现通常遵循一个非常简单的模式。Java中的大部分内存布局都非常简单明了。我的术语可能与Java术语不匹配,因为我没有做很多Java编程 通常,对象以指向其vtable的指针开始,然后有一组字段
谢谢大家详细信息在实现中(而不是规范中)。然而,实现通常遵循一个非常简单的模式。Java中的大部分内存布局都非常简单明了。我的术语可能与Java术语不匹配,因为我没有做很多Java编程 通常,对象以指向其vtable的指针开始,然后有一组字段跟随。字段是基本类型(int/bool/float)或指向对象的指针。对象就是这样。(类也是对象。)空指针类似于C,它们是无效的,不像Python,在Python中没有对象 在内部类中,有一个额外的隐藏字段指向外部类的实例。这是内部类访问外部类中数据的方式。匿名类也是这样工作的。静态方法只是类上的方法,而不是实例上的方法 vtable是所有魔法发生的地方。每个类都有自己的vtable,在所有对象之间共享。vtable包含有关该类的信息,例如其实例的大小以及字段的布局方式。此信息由垃圾收集器使用。vtable还有一个指向该类实现的所有方法的指针。调用方法时,运行时首先从对象中获取vtable指针,然后从vtable中获取方法指针,然后调用该方法并将该对象作为隐式参数传递给该方法。它类似于C++,但实现起来要简单得多。如果方法或类为“final”,则可以跳过该过程 我知道Java实际上没有“指针”,它有“符号句柄”之类的东西,但常见的实现只是使用普通的旧指针 比如当我 具有一个字段,该字段是 在外部类与 内部阶级。静态类看起来怎么样 与非静态不同 非静态内部(或匿名)类的实例将引用用于实例化它的外部类实例。这就是允许内部类中的方法引用封闭类中声明的实例级成员的原因。通常,该引用作为构造函数中隐藏的额外参数传递给内部类。但如果使用反射创建内部类实例,则必须显式提供该额外参数 (请注意,当匿名类在实例化它的方法范围内使用局部变量/参数时,会使用不同的机制…) 如果需要更多细节,可以使用javap来分解一些简单示例类的字节码 我只需要一个视觉参考
对不起,我不喜欢漂亮的图片:-)欢迎来到Java世界。与C语言不同,C语言的语言结构和内存表示几乎是一对一的映射,Java稍微复杂一些 首先,当人们谈到Java时,它可能意味着两件事:Java语言和Java平台。在这里,我的意思是Java是编程语言Java。用Java编写的代码首先被编译成字节码,即Java虚拟机的机器代码。如果您对Java语言的细节感兴趣,下面是。对于JVM,有两个 当我有一个字段是在外部类和内部类中定义的对象时,内存是什么样子的 我将解释为Java虚拟机中的内存布局是什么样子,因为物理布局取决于JVM的实现。为此我略读了一下 与Java语言一样,Java虚拟机操作两种类型:基本类型和引用类型。相应地,有两种值可以存储在变量中,作为参数传递,由方法返回,并对其进行操作:原语值和引用值 Java虚拟机希望几乎所有类型检查都在编译时完成,而不是由Java虚拟机本身完成。特别是,数据无需标记或可检查以确定类型 对对象的引用被认为具有Java虚拟机类型
reference
。reference
类型的值可以看作是指向对象的指针
所以答案似乎是,这两个字段看起来完全一样:reference
有用的链接
静态(嵌套)类的工作方式与顶级类完全相同。唯一的区别是它的名称前面有另一个类名。(如果查看编译后的.class文件,您会发现在名为Outer的类中嵌套名为Nested的类会得到类似于“Outer$Nested.class”的内容。)
内部类有一个隐藏字段,该字段是对其外部类的包含实例的引用。当你写作时:
class Outer {
final int x;
class Nested {
int y;
Nested(int y) {
this.y = y;
}
int bar() {
return x + y;
}
}
void foo() {
Nested n = new Nested(5);
}
}
就好像你写过:
class Outer {
final int x;
static class Nested {
Outer outer;
int y;
Nested(Outer outer, int y) {
this.outer = outer;
this.y = y;
}
int bar() {
return outer.x + y;
}
}
void foo() {
Nested n = new Nested(this, 5);
}
}
隐藏字段的名称(我在这里称为“外部”)是隐藏的
对你来说,虽然你可以通过说Outer来引用它。这是
内部类(其中Outer
当然是外部类的名称)。
同样,请注意,当内部类中的方法引用
在外部类中,引用实际上是通过隐藏的
对外部类的引用
关于访问控制(例如:私有)如何与n一起工作,还有一些额外的复杂性
public class I {
class inner {
public void ctor() {};
}
}
class I$inner {
// Field descriptor #6 LI;
final synthetic I this$0;
// Method descriptor #8 (LI;)V
// Stack: 2, Locals: 2
I$inner(I arg0);
0 aload_0 [this]
1 aload_1
2 putfield I$inner.this$0 : I [10]
5 aload_0 [this]
6 invokespecial java.lang.Object() [12]
9 return
Line numbers:
[pc: 0, line: 3]
Local variable table:
[pc: 0, pc: 10] local: this index: 0 type: I.inner
// Method descriptor #14 ()V
// Stack: 0, Locals: 1
public void ctor();
0 return
Line numbers:
[pc: 0, line: 4]
Local variable table:
[pc: 0, pc: 1] local: this index: 0 type: I.inner
}