在Java中加载类时如何管理内存?

时间:2015-05-27 06:56:14

标签: java jvm

想象一下,我有一个包含10个方法的类,我需要从类中实例化10个对象。 问题是: JVM是否会在对象创建时为10个实例分配10个不同的内存空间(我的意思是在我调用构造函数时,即新的MyClass();?或者它将加载类定义一次在内存和每个实例中调用这10个方法中的每一个时,在运行时,JVM会分配内存吗?

为了清除一些误解,我的问题是在创建对象时,我知道所有数据成员都分配在堆内存中,但我不确定尚未调用的方法是否已分配每个对象的内存不同?

3 个答案:

答案 0 :(得分:4)

  

JVM是否会在对象创建时为10个实例分配10个不同的内存空间(我的意思是在我调用构造函数时,即新的MyClass();

它可能会做,但是通过转义分析,它可以将它们放在堆栈上或完全消除它们。

  

或者它会在内存和每个实例中加载一次类定义,同时调用这10个方法中的每一个,在运行时,JVM会分配内存吗?

如果您有一个ClassLoader,您将获得该类的一个实例,但是如果每个实例都有自己的ClassLoader,您将在每个ClassLoader中获得该类的副本。注意:每个ClassLoader可以具有相同名称的不同版本的类。

  

为了清除一些误解,我的问题是在创建对象时,我知道所有数据成员都分配在堆内存中,

它在PermGen(Java< 7)或MetaSpace(Java 8 +)中堆存的类和方法信息(包括字节代码)

实际的实例在名义上被添加到堆中,但不一定是。

  

我不确定尚未调用的方法是否在内存中为每个对象分配不同的内容?

JVM经历了许多优化阶段,当你调用一个方法时,它可能会优化它,内联它甚至消除它。您可以通过在命令行上添加-XX:+PrintCompilation来查看正在编译(甚至重新优化)的方法。

答案 1 :(得分:3)

是。 类元数据被加载到 Permgen空间(Java8中的 MetaSpace )。因此,一旦类加载,所有方法都可用(静态和非静态)。尚未调用的方法也将作为此元数据的一部分加载。所有方法只加载一次。

答案 2 :(得分:-1)

在加载类时,类的所有方法(静态和非静态)也会加载到内存中。无论有多少人都在加载。

对于每个对象,JVM将分配不同的内存位置。

假设

MyClass m1 = new MyClass(); // one memory location

MyClass m2 = new MyClass(); // different location

MyClass m3 = m1; // same memory location of m1 object