简体   繁体   English

Java在内存中的含义是什么

[英]What does Java look like in memory

I am new to java and still learning. 我是java新手,还在学习。 I got my head around inner and anonymous classes. 我抓住了内心和匿名课程。 Now I have a technical question about how java looks like in memory, when allocating objects, defining classes, etc. 现在我有一个关于java在内存中的样子,分配对象,定义类等的技术问题。

Like what does memory look like when I have a field that is an object that is defined in an outside class vs an inner class. 就像当一个字段是一个在外部类和内部类中定义的对象时,内存的样子。 Do static classes look different than non static? 静态类看起来与非静态不同吗?

I just need a visual reference. 我只需要一个视觉参考。

Thanks Guys 多谢你们

The details are in the implementation (not the spec). 细节在实现中(不是规范)。 However, the implementations generally follow a very simple pattern. 然而,实现通常遵循非常简单的模式。 Most of the memory layout in Java is very simple and straightforward. Java中的大多数内存布局都非常简单明了。 My terminology may not match the Java terminology, since I don't do a lot of Java programming. 我的术语可能与Java术语不匹配,因为我没有做很多Java编程。

In general, an object starts with a pointer to its vtable, and then has a bunch of fields that follow. 通常,对象以指向其vtable的指针开始,然后有一堆字段。 Fields are either primitive types (int/bool/float) or pointers to objects. 字段是基本类型(int / bool / float)或指向对象的指针。 That's it for objects. 这就是对象。 (Classes are objects, too.) Null pointers are like C, they're invalid, not like Python, where None is an object. (类也是对象。)空指针就像C一样,它们是无效的,不像Python,其中None是一个对象。

In an inner class, there is an extra hidden field that points to an instance of the outer class. 在内部类中,有一个额外的隐藏字段,指向外部类的实例。 This is how inner classes access data in the outer class. 这是内部类访问外部类中的数据的方式。 Anonymous classes work the same way. 匿名类的工作方式相同。 Static methods are just methods on the class instead of methods on the instance. 静态方法只是类的方法而不是实例上的方法。

The vtable is where all the magic happens. vtable是所有魔法发生的地方。 Each class has its own vtable shared between all the objects. 每个类都有自己的vtable在所有对象之间共享。 The vtable has information about the class such as the size of its instances and how the fields are laid out. vtable具有关于类的信息,例如其实例的大小以及字段的布局方式。 This information is used by the garbage collector. 垃圾收集器使用此信息。 The vtable also has a pointers to all of the methods that the class implements. vtable还有一个指向该类实现的所有方法的指针。 When you call a method, the runtime first grabs the vtable pointer out of the object, then grabs the method pointer out of the vtable, then calls the method and passes the object to the method as an implicit parameter. 当您调用方法时,运行时首先从对象中获取vtable指针,然后将方法指针从vtable中取出,然后调用该方法并将该对象作为隐式参数传递给该方法。 It's similar to C++, but much simpler to implement. 它与C ++类似,但实现起来要简单得多。 The process can be skipped if the method or class is "final". 如果方法或类是“最终的”,则可以跳过该过程。

I know that Java doesn't really have "pointers", it has "symbolic handles" or somesuch, but the common implementations just use plain old pointers. 我知道Java并没有真正的“指针”,它有“符号句柄”或类似的东西,但常见的实现只使用普通的旧指针。

Welcome to the world of Java. 欢迎来到Java世界。 Unlike C language where the language construct and the memory representation maps pretty much one-to-one, Java is slightly more complicated. 与C语言不同,语言构造和内存表示几乎一对一地映射,Java稍微复杂一些。

First of all, when people speak of Java, it could mean two things: Java-the-language and Java-the-platform. 首先,当人们谈论Java时,它可能意味着两件事:Java-the-language和Java-the-platform。 Here, I'll mean Java to be the programming language Java. 在这里,我将Java称为Java编程语言。 The code written in Java is first compiled into bytecode, machine code for Java Virtual Machine. 用Java编写的代码首先被编译为字节码,Java虚拟机的机器代码。 If you are interested in the details of the language Java, here's The Java Language Specification . 如果您对Java语言的详细信息感兴趣,请参阅Java语言规范 And for JVM, there's The Java Virtual Machine Specification . 对于JVM,有Java虚拟机规范

what does memory look like when I have a field that is an object that is defined in an outside class vs an inner class. 当我有一个字段是一个在外部类和内部类中定义的对象时,内存是什么样的。

I'll interpret this to be what does the memory layout in Java Virtual Machine look like, since the physical layout is up to the implementation of the JVM. 我将这解释为Java虚拟机中的内存布局是什么样的,因为物理布局取决于JVM的实现。 For this I skimmed Structure of the Java Virtual Machine . 为此,我浏览了Java虚拟机的结构

Like the Java language, the Java Virtual Machine operates on two kinds of types: primitive types and reference types . 与Java语言一样,Java虚拟机也可以使用两种类型: 基本类型引用类型 There are, correspondingly, two kinds of values that can be stored in variables, passed as arguments, returned by methods, and operated upon: primitive values and reference values . 相应地,有两种值可以存储在变量中,作为参数传递,由方法返回,并对其进行操作: 原始值参考值

The Java Virtual Machine expects that nearly all type checking is done at compile time, not by the Java Virtual Machine itself. Java虚拟机期望几乎所有类型检查都在编译时完成,而不是由Java虚拟机本身完成。 In particular, data need not be tagged or otherwise be inspectable to determine types. 特别是,不需要标记数据或以其他方式检查数据以确定类型。

.... ....

A reference to an object is considered to have Java Virtual Machine type reference . 对对象的引用被视为具有Java虚拟机类型reference Values of type reference can be thought of as pointers to objects. 类型reference值可以被认为是指向对象的指针。

So the answer it seems, is that both fields would look exactly the same: reference . 所以答案似乎是两个字段看起来完全一样: reference

Like what does memory look like when I have a field that is an object that is defined in an outside class vs an inner class. 就像当一个字段是一个在外部类和内部类中定义的对象时,内存的样子。 Do static classes look different than non static? 静态类看起来与非静态不同吗?

An instance of non-static inner (or anonymous) class will have a reference to the outer class instance that was used to instantiate it. 非静态内部(或匿名)类的实例将引用用于实例化它的外部类实例。 This is what allows a method in the inner class to reference the instance-level members declared in the enclosing class. 这允许内部类中的方法引用封闭类中声明的实例级成员。 Normally, this reference is passed to the inner class as a hidden extra parameter in the constructor. 通常,此引用作为构造函数中的隐藏额外参数传递给内部类。 But if you use reflection to create an inner class instance, you have to supply that extra parameter explicitly. 但是如果使用反射来创建内部类实例,则必须显式提供该额外参数。

(Note that a different mechanism is used when an anonymous class uses the locals / parameters in the scope of the method that instantiates it ...) (注意,当匿名类使用实例化它的方法范围内的locals /参数时,会使用不同的机制...)

If you need the more details, you could use javap to disassemble the bytecodes of some simple example classes. 如果您需要更多详细信息,可以使用javap来反汇编一些简单示例类的字节码。

I just need a visual reference. 我只需要一个视觉参考。

Sorry, I don't do pretty pictures :-) 对不起,我不做漂亮的照片:-)

A static (nested) class works exactly the same way as a top-level class. 静态(嵌套)类的工作方式与顶级类的工作方式完全相同。 The only difference is that its name has another class name prefixing it. 唯一的区别是它的名字有另一个以它为前缀的类名。 (If you look at the compiled .class files you'll actually see that you'll get something like "Outer$Nested.class" for a class named Nested nested within a class named Outer.) (如果查看已编译的.class文件,您实际上会看到对于名为Nested的类嵌套在名为Outer的类中,您将获得类似“Outer $ Nested.class”的内容。)

An inner class has a hidden field which is a reference to the containing instance of its outer class. 内部类有一个隐藏字段,它是对其外部类的包含实例的引用。 When you write: 当你写:

class Outer {
  final int x;

  class Nested {
    int y;

    Nested(int y) {
      this.y = y;
    }

    int bar() {
      return x + y;
    }
  }

  void foo() {
    Nested n = new Nested(5);
  }
}

It's just as if you'd written: 就像你写的那样:

class Outer {
  final int x;

  static class Nested {
    Outer outer;
    int y;

    Nested(Outer outer, int y) {
      this.outer = outer;
      this.y = y;
    }

    int bar() {
      return outer.x + y;
    }
  }

  void foo() {
    Nested n = new Nested(this, 5);
  }
}

The name of that hidden field (that I've called "outer" here) is hidden to you, though you can refer to it by saying Outer.this inside of the inner class (where Outer is the name of your outer-class, of course). 隐藏字段的名称(我在这里称之为“外部”)对你来说是隐藏的,虽然你可以通过在内部类中说Outer.this来引用它(其中Outer是你的外部类的名字,当然)。 Likewise, notice that when a method in the inner class refers to something in the outer class, that reference is actually via that hidden reference to the outer class. 同样,请注意,当内部类中的方法引用外部类中的某些内容时,该引用实际上是通过对外部类的隐藏引用。

There are a few additional complications with regards to how access control (eg: private) works with nested/inner classes, but that doesn't really affect the "memory" question that you're asking. 关于访问控制(例如:private)如何与嵌套/内部类一起工作,还有一些额外的复杂性,但这并不会真正影响您所询问的“内存”问题。

public class I {
    class inner {
        public void ctor() {};
    }
}

Looks dissasemmbled like, you could use JAD 看起来像是一样,你可以使用JAD

class I$inner {

  // Field descriptor #6 LI;
  final synthetic I this$0;

  // Method descriptor #8 (LI;)V
  // Stack: 2, Locals: 2
  I$inner(I arg0);
     0  aload_0 [this]
     1  aload_1
     2  putfield I$inner.this$0 : I [10]
     5  aload_0 [this]
     6  invokespecial java.lang.Object() [12]
     9  return
      Line numbers:
        [pc: 0, line: 3]
      Local variable table:
        [pc: 0, pc: 10] local: this index: 0 type: I.inner

  // Method descriptor #14 ()V
  // Stack: 0, Locals: 1
  public void ctor();
    0  return
      Line numbers:
        [pc: 0, line: 4]
      Local variable table:
        [pc: 0, pc: 1] local: this index: 0 type: I.inner
}

As a hexdump it would start with 0xcafebabe 作为一个hexdump,它将从0xcafebabe开始

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM