I have a silly question for you all. Given the following Java Code
public void funct(String a) {
byte[] bytearr;
bytearr = new byte[a.getBytes().length];
bytearr = a.getBytes();
}
Does the new call change anything? In particular, is the code processed in a different way from
public void funct(String a) {
byte[] bytearr;
bytearr = a.getBytes();
}
I am asking because, when executed, both present the same results and I can't get if
- They're different (in the first case space is allocated and filled while in the second it's more like a "pointer assignation").
- They're the same and I overthink alot.
- Second one is wrong but JVM is smarter than me and fixes it.
More in general, any suggestion to observe memory allocations/magic behaviour behind JVM would be very appreciated.
Thanks!
They are different, let us take a look at the bytecode:
1. version:
L0
LINENUMBER 9 L0
ALOAD 0
ICONST_0
AALOAD
INVOKEVIRTUAL java/lang/String.getBytes ()[B
ARRAYLENGTH
NEWARRAY T_BYTE
ASTORE 1
L1
LINENUMBER 10 L1
ALOAD 0
ICONST_0
AALOAD
INVOKEVIRTUAL java/lang/String.getBytes ()[B
ASTORE 1
L2
LINENUMBER 11 L2
RETURN
L3
LOCALVARIABLE args [Ljava/lang/String; L0 L3 0
LOCALVARIABLE bytearr [B L1 L3 1
MAXSTACK = 2
MAXLOCALS = 2
2. version:
L0
LINENUMBER 9 L0
ALOAD 0
ICONST_0
AALOAD
INVOKEVIRTUAL java/lang/String.getBytes ()[B
ASTORE 1
L1
LINENUMBER 10 L1
RETURN
L2
LOCALVARIABLE args [Ljava/lang/String; L0 L2 0
LOCALVARIABLE bytearr [B L1 L2 1
MAXSTACK = 2
MAXLOCALS = 2
The difference is in those instructions comming from the extra line:
LINENUMBER 9 L0
ALOAD 0
ICONST_0
AALOAD
INVOKEVIRTUAL java/lang/String.getBytes ()[B
ARRAYLENGTH
NEWARRAY T_BYTE
ASTORE 1
This introduces additional overhead (getBytes
being called twice, more instructions). By invoking bytearr = a.getBytes()
jvm already handles the size of the array being stored.
But since the first initialization is redundant, it will probably be optimized by the compiler at some point (after enough runs). Still, there is no need for additional instructions and less readable code.