我已经学习了将近一年的Java,但在动态内存分配方面仍然感到困惑。
问题1:任何人都可以根据我写的步骤详细说明在下面的代码执行时内存中会发生什么(如果我错了请纠正我)?越详细越好。
问题2:如果我想更深入地了解JVM或Java内存,我应该阅读/访问哪种书籍/网站?
class Student {
private static int counter;
private String name;
private int age;
private String grade = "grade 1";
Student(String _name, int _age) {
this.name = _name;
this.age = _age;
}
public static void main(String[] args){
Student s = new Student("Emma", 6);
}
}
Student.class
文件加载,静态变量counter
在数据区域初始化。main()
被调用,JVM在堆栈上为本地变量s
分配内存。name
,age
和grade
分配存储空间,并将存储空间归零。grade
初始化为"grade 1"
。Student()
被调用以初始化新实例:JVM在堆栈上为_name
和_age
分配内存,将它们初始化为"Emma"
和6
,然后将其值复制到成员变量name
和age
。s
。答案 0 :(得分:2)
你有4个和5个不按顺序。构造函数首先以一种或另一种形式调用super()
,然后按文本顺序调用所有初始值设定项和匿名初始化块,然后在super()
调用后调用它们自己的主体(如果有的话)。您还在错误的位置分配和初始化_name
和_age
:它在构造函数被调用之前发生。有关详细信息,请参阅JLS和JVM规范。
答案 1 :(得分:0)
一些笔记;
在较新版本的Java上,如果从未使用静态字段,则无法保证会初始化。
对象的空间一次性初始化,而不是基于每个场。整个对象都是零(除了标题),而不仅仅是字段的保存位置。即,对象具有填充,它被清零,并且将8字节字段清零并不比单个长字段更慢。
无论代码如何编写,都会在对象的任何字段分配值之前调用构造函数。
第一次使用String文字时,还会创建String和底层char []或byte []。 grade
初始化为对该对象的引用。
正如@biziclop指出的那样(不仅仅是在理论上)这些事情都不可能发生,因为整个代码可以被优化为零(JIT今天可以做到这一点)它唯一没有做到的事情&#39 ; t do是阻止创建String文字,因为在代码已经预热到足以确定代码没有做任何事情之前很久就会发生这种情况。
注意:随着AOT进入Java 9,可能会将代码缩减为NO-OP。