Java虚拟机的数组处理

Java虚拟机的数组处理,java,arrays,performance,oop,jvm,Java,Arrays,Performance,Oop,Jvm,我有一个愚蠢的问题要问你们大家。给定以下Java代码 public void funct(String a) { byte[] bytearr; bytearr = new byte[a.getBytes().length]; bytearr = a.getBytes(); } 新电话有什么变化吗?特别是,代码的处理方式是否与 public void funct(String a) { byte[] bytearr; bytearr = a.getB

我有一个愚蠢的问题要问你们大家。给定以下Java代码

public void funct(String a) {
    byte[] bytearr;

    bytearr = new byte[a.getBytes().length];
    bytearr = a.getBytes();
}
新电话有什么变化吗?特别是,代码的处理方式是否与

public void funct(String a) {
    byte[] bytearr;

    bytearr = a.getBytes();
}
我这样问是因为,当执行时,两者都呈现相同的结果,我无法得到

它们在第一种情况下不同,空间被分配和填充,而在第二种情况下更像是指针分配。 他们是一样的,我想得太多了。 第二个是错误的,但JVM比我聪明,并且修复了它。 更一般地说,任何关于观察JVM背后的内存分配/魔法行为的建议都将非常感谢


谢谢

它们是不同的,让我们看看字节码:

一,。版本:

二,。版本:

不同之处在于额外一行中的说明:

LINENUMBER 9 L0
ALOAD 0
ICONST_0
AALOAD
INVOKEVIRTUAL java/lang/String.getBytes ()[B
ARRAYLENGTH
NEWARRAY T_BYTE
ASTORE 1
这会导致额外的开销,即调用两次getBytes,即调用更多指令。通过调用bytearr=a.getBytes,jvm已经处理了存储的数组的大小


但是,由于第一次初始化是冗余的,在运行足够多的时间后,编译器可能会在某个时候对其进行优化。不过,不需要额外的指令和可读性较差的代码。

它们是不同的,让我们看看字节码:

一,。版本:

二,。版本:

不同之处在于额外一行中的说明:

LINENUMBER 9 L0
ALOAD 0
ICONST_0
AALOAD
INVOKEVIRTUAL java/lang/String.getBytes ()[B
ARRAYLENGTH
NEWARRAY T_BYTE
ASTORE 1
这会导致额外的开销,即调用两次getBytes,即调用更多指令。通过调用bytearr=a.getBytes,jvm已经处理了存储的数组的大小


但是,由于第一次初始化是冗余的,在运行足够多的时间后,编译器可能会在某个时候对其进行优化。不过,不需要额外的指令和可读性较差的代码。

唯一的区别是,您在第一个代码段中创建了一个额外的、不必要的对象。如果要证明这一点,可以将第二个数组引用指向第一个数组,打印出它们的等价性,然后调用第一个数组上的string.getBytes并再次测试它们的等价性:

        String aString = new String("something");

        byte[] byteArray1 = new byte[aString.length()];
        byte[] byteArray2 = byteArray1;
        System.out.println(byteArray1==byteArray2);

        byteArray1 = aString.getBytes();
        System.out.println(byteArray1==byteArray2);

它在aString.getBytes之前输出true,因为引用指向同一个对象。然后aString.getBytes返回一个新的byte[]数组,因此byteArray1不再==byteArray2。这是否回答了问题,还是您在寻找其他内容?

唯一的区别是您在第一个代码段中创建了一个额外的、不必要的对象。如果要证明这一点,可以将第二个数组引用指向第一个数组,打印出它们的等价性,然后调用第一个数组上的string.getBytes并再次测试它们的等价性:

        String aString = new String("something");

        byte[] byteArray1 = new byte[aString.length()];
        byte[] byteArray2 = byteArray1;
        System.out.println(byteArray1==byteArray2);

        byteArray1 = aString.getBytes();
        System.out.println(byteArray1==byteArray2);

它在aString.getBytes之前输出true,因为引用指向同一个对象。然后aString.getBytes返回一个新的byte[]数组,因此byteArray1不再==byteArray2。这是否回答了问题,还是您在寻找其他东西?

两个代码块的最终结果是相同的。第一个版本做了一些不必要的额外工作

版本1

让我们一步一步地浏览第一个版本

第一步

bytearr = new byte[a.getBytes().length];
创建一个新的空数组,bytearr指向它

步骤2

bytearr = a.getBytes();
a、 getBytes创建第二个数组。bytearr更新为指向该新阵列。旧的蓝色数组现在是垃圾,因为不再保存对它的引用。JVM的垃圾收集器最终将释放它所占用的内存

版本2

bytearr直接指向由a.getBytes创建的数组。最终结果是一样的,但这个版本更有效

有关版本1的更多详细信息

实际上,版本1在调用a.getBytes.length期间创建了更多的数组。最初的解释跳过了它以保持简单

因此,在版本1中实际上涉及3个阵列实例:

调用a.getBytes.length期间创建的一个,用于测量simplicty图表中未显示的大小。 由新字节[…]创建的空字节,其大小为蓝色字节。 在第二次调用a.getBytes时创建的是绿色的。
两个代码块的最终结果是相同的。第一个版本做了一些不必要的额外工作

版本1

让我们一步一步地浏览第一个版本

第一步

bytearr = new byte[a.getBytes().length];
创建一个新的空数组,bytearr指向它

步骤2

bytearr = a.getBytes();
a、 getBytes创建第二个数组。bytearr更新为指向该新阵列。旧的蓝色数组现在是垃圾,因为不再保存对它的引用。JVM的垃圾收集器最终将释放它所占用的内存

版本2

bytearr直接指向由a.getBytes创建的数组。最终结果是一样的,但这个版本更有效

有关版本1的更多详细信息

实际上,版本1在调用a.getBytes.length期间创建了更多的数组。最初的解释跳过了它以保持简单

所以实际上有3个 版本1中涉及的阵列实例:

调用a.getBytes.length期间创建的一个,用于测量simplicty图表中未显示的大小。 由新字节[…]创建的空字节,其大小为蓝色字节。 在第二次调用a.getBytes时创建的是绿色的。
INTA和INTA之间有什么不同;a=1;a=2和int a;a=2?好的,发布的代码做的更多:第一个创建一个字节数组,但当bytearr的值接收到一个新值时,在下一个命令中该数组被丢弃。区别在于第一个版本中的第一个赋值完全是浪费时间和空间;a=1;a=2和int a;a=2?好的,发布的代码做的更多:第一个创建一个字节数组,但当bytearr的值接收到一个新值时,在下一个命令中会丢弃该数组。区别在于第一个版本中的第一个赋值完全是浪费时间和空间。