What does Java look like in memory
I am new to java and still learning. I got my head around inner and anonymous classes. Now I have a t开发者_如何学Cechnical question about how java looks like in memory, when allocating objects, defining classes, etc.
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
Helpful link
http://www.artima.com/insidejvm/ed2/jvm6.html
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. My terminology may not match the Java terminology, since I don't do a lot of Java programming.
In general, an object starts with a pointer to its vtable, and then has a bunch of fields that follow. Fields are either primitive types (int/bool/float) or pointers to objects. 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.
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. Each class has its own vtable shared between all the objects. The vtable has information about the class such as the size of its instances and how the fields are laid out. This information is used by the garbage collector. The vtable also has a pointers to all of the methods that the class implements. 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. It's similar to C++, but much simpler to implement. 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.
Welcome to the world of Java. Unlike C language where the language construct and the memory representation maps pretty much one-to-one, Java is slightly more complicated.
First of all, when people speak of Java, it could mean two things: Java-the-language and Java-the-platform. Here, I'll mean Java to be the programming language Java. The code written in Java is first compiled into bytecode, machine code for Java Virtual Machine. If you are interested in the details of the language Java, here's The Java Language Specification. And for JVM, there's The Java Virtual Machine Specification.
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. For this I skimmed Structure of the Java Virtual Machine.
Like the Java language, the Java Virtual Machine operates on two kinds of types: primitive types and reference types. 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. 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
. Values of typereference
can be thought of as pointers to objects.
So the answer it seems, is that both fields would look exactly the same: 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 ...)
If you need the more details, you could use javap to disassemble the bytecodes of some simple example classes.
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.)
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).
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.
public class I {
class inner {
public void ctor() {};
}
}
Looks dissasemmbled like, you could use 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
精彩评论