Java类实例化-内存中有什么?

Java类实例化-内存中有什么?,java,classloader,instantiation,Java,Classloader,Instantiation,我有一个基本问题。考虑这个简单的代码: class A{ void someMethod(){ B b = new B(); // Line 3 B c = new B(); // Line 4 } } 当执行第3行时,类B被加载到内存中(即:我们为一个“class”类型的对象分配了物理空间(比如使用一个id-classLaoder1.B),该类型的class包含类B的代码) 问题1#接下来会发生什么类B的实例(表示B的状态)是基于classLoader.B

我有一个基本问题。考虑这个简单的代码:

class A{
   void someMethod(){
      B b = new B(); // Line 3
      B c = new B(); // Line 4
   }
}
当执行第3行时,类B被加载到内存中(即:我们为一个“class”类型的对象分配了物理空间(比如使用一个id-
classLaoder1.B
),该类型的class包含类B的代码)

问题1#接下来会发生什么类B的实例(表示B的状态)是基于
classLoader.B
实际包含B的信息这一事实创建的(分配的物理内存)


问题2,也就是,在第4行,自从<代码>类加载器.b/COD>存在于内存中,在内存中创建包含C状态的对象。

< P> B和C是B类的实例,考虑它们是变量,所以它们将分别存储在内存中。b包含类b的信息(该类相当于一个结构),因此您可能有一个具有变量名的类Person,您有两个实例:p1和p2。每一个在内存中都有不同的名称和不同的地方:

b和c是B类的实例,将它们视为变量,因此它们将分别存储在内存中。b包含类b的信息(该类相当于一个结构),因此您可能有一个具有变量名的类Person,您有两个实例:p1和p2。每个人都有不同的名字和不同的记忆位置。好吧,你的例子和描述有点模糊,不能用简短的方式回答你的问题


您指的是不同的类加载器,但在加载哪个类时没有包含任何示例代码。在当前的形式下,由于缺少返回值,代码甚至无法编译——但让我们继续回答您的问题

堆是JVM在启动时创建的内存区域,在运行时可以动态地增加和减少。它分为不同的部分。因此,PermGen空间是为类和绑定到类(如静态成员)的东西保留的,如果您处理提供某种热部署功能的应用程序服务器或插件机制,您将不得不处理它。(更准确地说,在Sun的JVM中,和并不真正属于堆,但是不同的JVM供应商可能有不同的定义)

调用
someMethod()
时可能会出现两种情况:

  • B在应用程序启动时已由应用程序类加载器加载
  • B包含在由子类加载器加载的类中
在第一种情况下,类定义的内存在启动时在堆的PermGen空间内分配,并且仅在应用程序关闭时释放。在后一种情况下,该类的内存也存储在堆的PermGen空间中,但是在调用应该加载该类的类加载器的
loadClass(…)
时。在这里,如果没有强引用指向由该类装入器装入的任何类,则可以释放内存。通常,枚举或单例类(它们自身具有强引用)会阻止正确卸载这些加载的字节,从而导致内存泄漏

如果您实现了其中一个应用程序框架并对其进行了调试,那么您将看到在调试时会发生什么。要通过类加载器加载类,将调用
loadClass(…)
方法,该方法首先检查它是否已加载该类,然后询问其家长是否知道该类(该方法还检查她是否已加载该类或其家长…)。仅当类之前没有加载(由该类加载器或任何父类加载)时,当前(子)类加载器将执行
findClass(…)
,该加载器还应调用
defineClass()
,该加载器实际上将字节从某个输入文件或流转换为
表示。
Class
对象包含blueprint(方法的签名,包括参数的数量和类型、返回值和抛出的异常)。在尝试加载一个类时,通常会加载扩展类以及定义的接口(如果在类加载程序树中还不知道的话)——但是还没有加载包含成员的类型!当类将被实例化时,它们将被加载

创建新实例时,
new
操作符在内部和外部调用
newInstance(…)
方法。因此,如果当前类加载器或其父类尚不知道成员的类型,则将在分配任何值之前加载该成员。然后,执行类的构造函数(根据新操作调用的构造函数),并将值分配给堆上的变量所占用的内存(通常在Eden空间中)。在内存中构造对象后,新操作符将返回对该对象的引用,并且该对象已准备好在代码中使用

在您的示例中,
c
的实例化方式与
b
相同-首先,类加载器必须检查类
b
是否已加载。因为它以前加载过
B
,所以它只是从本地缓存中获取
B
,然后返回类。接下来,对类执行
newInstance(…)
方法来实例化一个新对象。因此,再次在堆上为成员变量分配内存—在初始检查是否已加载所需的类之后—执行构造函数并返回对新创建和初始化对象的引用

如果您的类有,它们将被分配到PermGen空间,因为它们属于该类,并且在所有实例中共享

需要注意的一点是:如果
c
应该由对等方或对等方的子类加载器(CL2)加载,而
b
是由姐妹类加载器(CL1)定义的(因此没有父类实际定义了该类),那么对等类