我来自C的操作系统和背景,编译代码时世界很简单。需要处理和理解堆栈,堆文本部分等。
当我开始学习Java(我知道JVM和垃圾收集器)时,我对静态方法感到很开心。根据我的理解,类的所有实例都在堆中创建,然后进行清理。但是,对于静态方法,您不需要该类的实例。
那么,有人可以解释一下非静态方法和静态方法在内存模型上的区别。它们都位于内存的文本部分。或者我完全搞砸了。
由于
答案 0 :(得分:2)
在Java中,类的字节码(包括它们的方法,包括静态和实例)是堆的一部分(通常在长寿命对象的特殊“永久生成”部分中)。
类也可以被垃圾收集,但这通常不会发生太多(仅当从非系统类加载器加载类并且整个类加载器变得过时时,例如卸载Web应用程序时)。 / p>
但是,对于静态方法,您不需要该类的实例。
右。但是所有方法都是类定义的一部分,并在加载类时加载到一起。即使你从未创建类的实例,所有实例方法的代码也将被加载到堆内存中。
然后对本机代码进行JIT编译:使用Hotspot,常用方法的字节码将进一步编译为本机代码。这样做的结果确实会在堆外部的某个地方进入本机内存,而这只发生在实际使用的方法中(静态或非静态)。
答案 1 :(得分:0)
您理解在堆中创建类的所有实例 ...
不完全正确,所有类都被编译为对象字节代码,否则JVM无需执行任何操作。实例和静态方法都生成相同的对象字节代码。即使非静态类也只生成其对象字节代码的单个版本。所有实例类都有自己的指针,指向它们在单个字节代码副本中的执行位置。真正的区别在于班级的数据成员。非静态类的每个实例都必须拥有自己的所有非静态数据成员(变量)的副本,但静态数据成员在内存中只有一个副本,因为类的静态数据成员由所有实例共享那个类静态或非静态。
静态类或非静态类的静态数据成员都在内存中拥有自己的单个副本。
非静态类在内存中只有一个目标代码副本,只有非静态数据才能在内存中为每个实例获取副本。