Talking about the object and reference

Objects and references

new object

The most simple example:

new Object();

Simply put, new Object () is an instance of type Object created (instance), allocated in the JVM heap memory

To public method as an example, look at:

PS: Whether the method is public or private / protected / package method, or method of construction is, even in a static block, static variables, instance variables, new Object for this action, it is very much the same

public class Test {
	public void fun1() {
        Object o = new Object();
    }
}

In fun1 method of Test class is instantiated an Object, and assigned to a variable of type Object, when this method is called, what happened?

1. Perform javac Test.javacompiled to Test.classfile

2. execution javap -v Test.class, you can view the compiled .classbyte code file. Here are just a fun1

public void fun1();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=1
         0: new           #2                  // class java/lang/Object
         3: dup
         4: invokespecial #1                  // Method java/lang/Object."<init>":()V
         7: astore_1
         8: return
      LineNumberTable:
        line 3: 0
        line 4: 8

Focusing Code section

stack = 2 indicates that the process requires a depth of operand stack 2

locals = 2 indicates that the process requires two local variable space of Slot

Here is followed by the offset and the corresponding JVM instruction set, we can analyze these step by step set of instructions to do something

First, the initialization of the operand stack and local variable space is such that:

Instruction Set Corresponding CODE
0: new, create an instance of a type java.lang.Object, and its reference value onto the operand stack of the stack (PS: This does not refer to a reference value Object o)
of the operand stack: [free], [objectRef]
local variable table: [the this], [free]
new Object()
3: dup, copy the value stack operand stack, and stack the operand value onto the stack
operand stack: [objectRef], [objectRef]
local variable table: [the this], [free]
new Object()
4: invokespecial, calling the java.lang.Object " ": ()v The method of
the operand stack: [free], [objectref]
local variable table: [the this], [free]
new Object()
7: astore_1, the reference value of the top of the stack into local variables second
operand stack: [free], [free]
local variable table: [the this], [objectRef]
Object o = new Object (), mainly the assignment operator
8: return, from the current method returns void

From the analysis of the above steps can be found, a simple method in a new Object operation, the JVM is executed three instructions, namely:

  • Create object and stack reference value
  • Copy the top of the stack value
  • Call the superclass constructor

This reference value objectref more easily lead to ambiguity, we usually say that the reference is to Object o = new Object()the give the operator the left of the Object O , be noted that this sentence does not create a reference, but the reference to Object instance, into local variables

VS is not assigned assignment

When you create objects to use, look at this situation

Object o = new Object();
o.toString();

Create an instance of type Object, and then call its toStringmethod

The same wording can also be this way:

new Object().toString();

Is there any difference of these two methods? By JVM instructions to look

Source:

public class Test {
	public void invokeWithoutReference() {
		new Object().toString();
	}
	public void invokeWithReference() {
		Object o = new Object();
		o.toString();
	}
}

Instruction set ( javap -v Test.classretaining only the instruction set section):

public void invokeWithoutReference();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: new           #2                  // class java/lang/Object
         3: dup
         4: invokespecial #1                  // Method java/lang/Object."<init>": ()V
         7: invokevirtual #3                  // Method java/lang/Object.toString:()Ljava/lang/String;
        10: pop
        11: return

  public void invokeWithReference();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=1
         0: new           #2                  // class java/lang/Object
         3: dup
         4: invokespecial #1                  // Method java/lang/Object."<init>": ()V
         7: astore_1
         8: aload_1
         9: invokevirtual #3                  // Method java/lang/Object.toString:()Ljava/lang/String;
        12: pop
        13: return

There is no difference between the reference and is the reference, in invokeWithReferencethe generating Objectthe examples, executed astore_1and aload_1two instructions, wherein:

astore_1Shows a stack reference value is stored in the second local variable table Slot, representing the assignment operator ( =) do

aload_1Said the second reference type local variable stack pushed onto the operand stack

Specifically, at two different methods of instruction execution sets:

invokeWithoutReference

Instruction Set Corresponding CODE
0: new, create an instance of a type java.lang.Object, stack and its reference value onto the operand stack
operand stack: [free], [objectRef]
local variable table: [the this]
new Object()
3: dup, copy the value stack operand stack, and stack the operand value onto the stack
operand stack: [objectRef], [objectRef]
local variable table: [the this]
new Object()
4: invokespecial, calling the java.lang.Object " ": ()v The method of
the operand stack: [free], [objectref]
local variable table: [the this]
new Object()
7: invokevirtual, toString java.lang.Object method invocation because toString method returns a value, the result will be performed where the stack is pushed into
the operand stack: [free], [java.lang.String]
local variable table : [the this]
new Object().toString();
10: pop, the top of the stack value pop
operation of stack: [free], [free]
local variable table: [the this]
new Object().toString();
11: return, return void from the current method

invokeWithReference

Instruction Set Corresponding CODE
0: new, create an instance of a type java.lang.Object, and its reference value onto the top of stack operand stack of
the operand stack: [free], [objectRef]
local variable table: [the this], [idle ]
new Object()
3: dup, copy the value stack operand stack, and stack the operand value onto the stack
operand stack: [objectRef], [objectRef]
local variable table: [the this], [free]
new Object()
4: invokespecial, calling the java.lang.Object " ": ()v The method of
the operand stack: [free], [objectref]
local variable table: [the this], [free]
new Object()
7: astore_1, the reference value of the top of the stack into local variables second
operand stack: [free], [free]
local variable table: [the this], [objectRef]
Object o = new Object();
8: aload_1,将第二个本地变量推入栈顶
操作数栈:[空闲], [objectref]
局部变量表:[this], [objectref]
9: invokevirtual,调用java.lang.Object的toString方法,因为toString方法有返回值,所以这里会将执行的结果推入栈顶
操作数栈:[空闲], [java.lang.String]
局部变量表:[this], [objectref]
new Object().toString();
12: pop,将栈顶数值弹出
操作数栈:[空闲], [空闲]
局部变量表:[this], [objectref]
new Object().toString();
13: return,从当前方法返回void

引用?

首先,什么是引用?

《深入理解JVM虚拟机》一书中多次对Java的引用进行了讨论

对象引用(reference类型,它不等同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或其他与此对象相关的位置)——《深入理解JVM虚拟机》 2.2.2 Java虚拟机栈

建立对象是为了使用对象,我们的Java程序需要通过栈上的reference数据来操作堆上的具体对象。——《深入理解JVM虚拟机》 2.3.3 对象的访问定位

一般来说,虚拟机实现至少都应当能通过这个引用做到两点,一是从此引用中直接或间接地查找到对象在Java堆中地数据存放地起始地址索引,二是此引用中直接或间接地查找到对象所属数据类型在方法区中的存储的类型信息 ——《深入理解JVM虚拟机》 8.2.1 局部变量表

对于new Object()来说,JVM执行的new(0xbb)指令天然的就会将新实例的引用压入操作数栈的栈顶

Object o = new Object()只是利用=运算符,让JVM执行了astore_n指令,将这个引用保存到了局部变量表中,以便我们以后可以直接通过o.xxx()来对这个实例做一些操作

等到我们需要使用的时候,JVM再通过aload_n将指定的局部变量表中的引用类型值推到操作数栈的栈顶进行后续操作

所以在我看来,Object o其实是一个引用类型的本地变量

创建对象到底赋值吗?

回到初衷,是否定义一个引用类型的本地变量,没有一个绝对的优劣

Object o = new Object()仅仅是比new Object()多在局部变量表中保存了一个Object o引用类型,但它可以让我们在创建了实例之后,重复对这个实例进行操作

new Object()在进行了new Object().toString()这种方式的调用之后,由于局部变量表中没有了该实例的引用,操作数栈中的那个两个由dup产生的两个引用,也已经分别因为invokespecialinvokevirtual弹出栈了,所以这个对象已经没有指向它的引用了

如果我们对于实例只是一次性调用,那么直接new Object()的方式也未尝不可

Guess you like

Origin www.cnblogs.com/shiyu404/p/12574905.html