rol*_*luo 4 java static heap-memory permgen
我已经阅读了一些关于这个主题的帖子:
但我对它们所说明的概念感到困惑:
静态方法(实际上是所有方法)以及静态变量都存储在堆的PermGen部分中,因为它们是反射数据的一部分(类相关数据,而不是实例相关).
因此,方法,无论是否static只存储在类中的堆上的一个副本.现在只有一个副本在类中,我解释为所有方法都属于该类,那么为什么Java只能使用实例化的实例调用非静态方法?
为什么我们有非静态方法属于实例的概念,而不是类?
这个故事的另一面需要提及.当你上课时,说Bar:
public class Bar {
public static void doSomething() { ... }
public void doSomethingElse() { ... }
}
Run Code Online (Sandbox Code Playgroud)
在堆上签名doSomethingElse不是,doSomethingElse()但doSomethingElse(Bar this).相反doSomething,没有参数(因此你不能this从静态方法调用- 没有this调用).
当你有这样的电话时:
Bar bar = new Bar();
bar.doSomethingElse();
Run Code Online (Sandbox Code Playgroud)
它只是一个语法糖:
doSomethingElse(bar); // I neglected here for simplification but the name of the method in the compiled code also includes the name of the class.
Run Code Online (Sandbox Code Playgroud)
定义扩展类时Foo:
public class Foo extends Bar {
@Override
public void doSomethingElse() { ... }
}
Run Code Online (Sandbox Code Playgroud)
另一种方法是创建的doSomethingElse(Foo this).接下来就是一个虚拟表(如果你不熟悉这个术语,请阅读它) - 每个类都有一个虚拟表,它将方法签名映射到具体代码.在运行时调用方法时,根据实例的动态类型,在类(而不是实例)虚拟表中搜索正确的实现.
所以完整的例子就是(当然这只是一个简化):
Java语法(语法糖):
Bar b = new Foo();
b.doSomethingElse();
Run Code Online (Sandbox Code Playgroud)
真正发生的事情(简化):
// Step 1: Get the correct overriden method for Foo class from the virtual table
// Step 2: Invoke the method with the instance "b" as the first parameter (the "this" parameter)
Foo.getMethodFromVirtualTable("doSomethingElse").invoke(b);
Run Code Online (Sandbox Code Playgroud)
这当然只是一种简化,但就像它发生的那样.
事实上,当你想到它时,所有方法在内存中都是静态的(这就是它们驻留的原因PermGen).编译器为每个类使用静态虚拟表,以便调用正确的方法.这允许多态性.
| 归档时间: |
|
| 查看次数: |
788 次 |
| 最近记录: |