Java Class 引用 Classes 的加载机制
Java Class loading mechanism for referenced Classes
当 class A
被加载时,假设 A
的字节码引用了许多其他 classes。假设 class A
如下所示。
class A extends B implements C,D {
static E e;
F f;
A() {
G g = new G();
}
void print(H h) {
}
}
JVM 是否加载了 A
使用的所有 classes?或者在初始化 class 之前它不会理会它们?
如果至少加载了其中一些,它们会在 A
完成后加载吗?或 A's
加载将暂停,直到所需的 class 加载?
对于这个问题,假设其他 class 中的 none 已经加载。甚至超级 class B
和接口 C
& D
.
要理解这一点,让我们了解一些基础知识。这将帮助任何新手理解 JAVA.
中的延迟加载
如果您熟悉 Netscape 的 Web 浏览器并且使用过 3.x 和 4.x 这两个版本,您无疑会注意到 Java 运行时加载方式的不同。如果您在 Netscape 3 启动时查看初始屏幕,您会注意到它加载了各种资源,包括 Java。但是,当您启动 Netscape 4.x 时,它不会加载 Java 运行时——它会一直等到您访问包含该标记的网页。这两种方法说明了急切实例化(在需要时加载它)和惰性实例化(在加载它之前等待它被请求,因为它可能永远不需要)的技术。
这两种方法都有缺点:一方面,如果在会话期间未使用资源,则总是加载资源可能会浪费宝贵的内存;另一方面,如果它还没有被加载,那么当资源第一次被需要时,你要付出加载时间的代价。
将惰性实例化视为一种资源保护策略
Java 中的惰性实例化分为两类:
- 延迟 class 加载
- 列表项
懒惰class加载
Java 运行时为 classes 内置了惰性实例化。 类 仅在首次引用时加载到内存中。 (它们也可能首先通过 HTTP 从 Web 服务器加载。)
MyUtils.classMethod(); //first call to a static class method
Vector v = new Vector(); //first call to operator new
惰性 class 加载是 Java 运行时环境的一项重要功能,因为它可以在某些情况下减少内存使用。例如,如果程序的一部分从未在会话期间执行,则永远不会加载仅在程序的该部分引用的 classes。
惰性对象创建
惰性对象创建与惰性 class 加载紧密相关。第一次在以前未加载的 class 类型上使用 new 关键字时,Java 运行时将为您加载它。惰性对象创建可以比惰性 class 加载更大程度地减少内存使用。
为了介绍惰性对象创建的概念,让我们看一个简单的代码示例,其中 Frame 使用 MessageBox 来显示错误消息:
public class MyFrame extends Frame
{
private MessageBox mb_ = new MessageBox();
//private helper used by this class
private void showMessage(String message)
{
//set the message text
mb_.setMessage( message );
mb_.pack();
mb_.show();
}
}
在上面的例子中,当MyFrame的一个实例被创建时,MessageBox实例mb_也被创建。递归地应用相同的规则。因此,在 class MessageBox 的构造函数中初始化或分配的任何实例变量也会在堆外分配,依此类推。如果 MyFrame 的实例不用于在会话中显示错误消息,我们就会不必要地浪费内存。
在这个相当简单的例子中,我们真的不会收获太多。但是,如果您考虑一个更复杂的 class,它使用许多其他 classes,而这些 classes 又递归地使用和实例化更多对象,潜在的内存使用量会更加明显。
public final class MyFrame extends Frame
{
private MessageBox mb_ ; //null, implicit
//private helper used by this class
private void showMessage(String message)
{
if(mb_==null)//first call to this method
mb_=new MessageBox();
//set the message text
mb_.setMessage( message );
mb_.pack();
mb_.show();
}
}
如果你仔细看一下showMessage(),你会发现我们首先判断实例变量mb_是否等于null。由于我们没有在声明点初始化 mb_,Java 运行时已经为我们处理了这个。因此,我们可以安全地继续创建 MessageBox 实例。以后所有对 showMessage() 的调用都会发现 mb_ 不等于 null,因此跳过对象的创建并使用现有实例。
结论:它会加载所有依赖的对象,一旦它们被子对象初始化entities.To减少内存占用我们应该仔细寻找这些设计模式像,虚拟代理,延迟初始化
当 class A
被加载时,假设 A
的字节码引用了许多其他 classes。假设 class A
如下所示。
class A extends B implements C,D {
static E e;
F f;
A() {
G g = new G();
}
void print(H h) {
}
}
JVM 是否加载了 A
使用的所有 classes?或者在初始化 class 之前它不会理会它们?
如果至少加载了其中一些,它们会在 A
完成后加载吗?或 A's
加载将暂停,直到所需的 class 加载?
对于这个问题,假设其他 class 中的 none 已经加载。甚至超级 class B
和接口 C
& D
.
要理解这一点,让我们了解一些基础知识。这将帮助任何新手理解 JAVA.
中的延迟加载如果您熟悉 Netscape 的 Web 浏览器并且使用过 3.x 和 4.x 这两个版本,您无疑会注意到 Java 运行时加载方式的不同。如果您在 Netscape 3 启动时查看初始屏幕,您会注意到它加载了各种资源,包括 Java。但是,当您启动 Netscape 4.x 时,它不会加载 Java 运行时——它会一直等到您访问包含该标记的网页。这两种方法说明了急切实例化(在需要时加载它)和惰性实例化(在加载它之前等待它被请求,因为它可能永远不需要)的技术。
这两种方法都有缺点:一方面,如果在会话期间未使用资源,则总是加载资源可能会浪费宝贵的内存;另一方面,如果它还没有被加载,那么当资源第一次被需要时,你要付出加载时间的代价。
将惰性实例化视为一种资源保护策略
Java 中的惰性实例化分为两类:
- 延迟 class 加载
- 列表项
懒惰class加载
Java 运行时为 classes 内置了惰性实例化。 类 仅在首次引用时加载到内存中。 (它们也可能首先通过 HTTP 从 Web 服务器加载。)
MyUtils.classMethod(); //first call to a static class method
Vector v = new Vector(); //first call to operator new
惰性 class 加载是 Java 运行时环境的一项重要功能,因为它可以在某些情况下减少内存使用。例如,如果程序的一部分从未在会话期间执行,则永远不会加载仅在程序的该部分引用的 classes。
惰性对象创建
惰性对象创建与惰性 class 加载紧密相关。第一次在以前未加载的 class 类型上使用 new 关键字时,Java 运行时将为您加载它。惰性对象创建可以比惰性 class 加载更大程度地减少内存使用。
为了介绍惰性对象创建的概念,让我们看一个简单的代码示例,其中 Frame 使用 MessageBox 来显示错误消息:
public class MyFrame extends Frame
{
private MessageBox mb_ = new MessageBox();
//private helper used by this class
private void showMessage(String message)
{
//set the message text
mb_.setMessage( message );
mb_.pack();
mb_.show();
}
}
在上面的例子中,当MyFrame的一个实例被创建时,MessageBox实例mb_也被创建。递归地应用相同的规则。因此,在 class MessageBox 的构造函数中初始化或分配的任何实例变量也会在堆外分配,依此类推。如果 MyFrame 的实例不用于在会话中显示错误消息,我们就会不必要地浪费内存。
在这个相当简单的例子中,我们真的不会收获太多。但是,如果您考虑一个更复杂的 class,它使用许多其他 classes,而这些 classes 又递归地使用和实例化更多对象,潜在的内存使用量会更加明显。
public final class MyFrame extends Frame
{
private MessageBox mb_ ; //null, implicit
//private helper used by this class
private void showMessage(String message)
{
if(mb_==null)//first call to this method
mb_=new MessageBox();
//set the message text
mb_.setMessage( message );
mb_.pack();
mb_.show();
}
}
如果你仔细看一下showMessage(),你会发现我们首先判断实例变量mb_是否等于null。由于我们没有在声明点初始化 mb_,Java 运行时已经为我们处理了这个。因此,我们可以安全地继续创建 MessageBox 实例。以后所有对 showMessage() 的调用都会发现 mb_ 不等于 null,因此跳过对象的创建并使用现有实例。
结论:它会加载所有依赖的对象,一旦它们被子对象初始化entities.To减少内存占用我们应该仔细寻找这些设计模式像,虚拟代理,延迟初始化