I commented earlier on this question ("Why java.lang.Object is not abstract?") stating that I'd heard that using a byte[0]
as a lock was slightly more efficient than using an java.lang.Object
. I'm sure I've read this somewhere but I can't recall where: Does anyone know if this is actually true?
I suspect it's due to the instantiation of byte[0]
requiring slightly less byte code than Object
, although it was pointed out that byte[0]
requires additional storage in order to store the length field and so it sounds like this might negate any benefit.
Object Lock in JavaWhenever an object is created, an object lock also gets created with it. Monitor is an object which is used as a mutual exclusive lock. Monitor can be owned by one thread only. To execute any block, a thread needs to acquire an object lock associated with that object.
A bytearray is always created using the bytearray() built-in function. bytearray objects are mutable.
A lock may be a tool for controlling access to a shared resource by multiple threads. Commonly, a lock provides exclusive access to a shared resource: just one thread at a time can acquire the lock and everyone accesses to the shared resource requires that the lock be acquired first.
With byte arrays, we can store binary data. This data may be part of a data file, image file, compressed file or downloaded server response. Array info. With byte arrays, we have an ideal representation of this data. The byte array type allows us to store low-level representations.
Using java.lang.instrument.Instrumentation to check the sizes:
Object uses 8 bytes, byte[0] needs 16 bytes. (not sure if the size is in bytes, not documented).
I also got the time to create an Object and a byte[0] (2 times): Object is the winner.
(all tests run on a DELL laptop, Intel 2GHz, Windos XP)
client
VMjava version "1.6.0_16"
Java(TM) SE Runtime Environment (build 1.6.0_16-b01)
Java HotSpot(TM) Client VM (build 14.2-b01, mixed mode)
an implementation-specific approximation of the amount of storage
Object = 8
byte[0] = 16
time to create 1000000000 instances
Object: elapsed=11,140 cpu=9,766 user=9,703 [seconds]
byte[0]: elapsed=18,248 cpu=15,672 user=15,594 [seconds]
time to create 1000000000 instances
Object: elapsed=11,135 cpu=9,828 user=9,750 [seconds]
byte[0]: elapsed=18,271 cpu=15,547 user=15,469 [seconds]
server
VMjava version "1.6.0_16"
Java(TM) SE Runtime Environment (build 1.6.0_16-b01)
Java HotSpot(TM) Server VM (build 14.2-b01, mixed mode)
an implementation-specific approximation of the amount of storage
Object = 8
byte[0] = 16
time to create 1000000000 instances
Object: elapsed=8,441 cpu=7,156 user=7,125 [seconds]
byte[0]: elapsed=11,237 cpu=8,609 user=8,500 [seconds]
time to create 1000000000 instances
Object: elapsed=8,501 cpu=7,234 user=7,156 [seconds]
byte[0]: elapsed=11,023 cpu=8,688 user=8,641 [seconds]
I will stay with new Object()
, not only because of readability :-)
public class ObjectArrayCompare {
private static Object o;
public static void main(String[] args) {
Instrumentation instr = InstrumentationAgent.getInstrumentation();
if (instr == null) {
System.err.println("No Instrumentation, use \"-javaagent:Instrumentation.jar\"");
return;
}
System.out.println();
System.out.println("an implementation-specific approximation of the amount of storage");
System.out.println("Object = " + instr.getObjectSize(new Object()));
System.out.println("byte[0] = " + instr.getObjectSize(new byte[0]));
System.out.println();
final int MAX = (int) 1.0e9;
Timer timer;
Times times;
for (int j = 0; j < 2; j++) {
System.out.println("time to create " + MAX + " instances");
timer = new Timer();
for (int i = 0; i < MAX; i++) {
o = new Object();
}
times = timer.times();
System.out.println("Object: " + times);
timer = new Timer();
for (int i = 0; i < MAX; i++) {
o = new byte[0];
}
times = timer.times();
System.out.println("byte[0]: " + times);
System.out.println();
}
}
}
Timer* uses ThreadMXBean
to get the times.
*Timer is a class I made for timming, it is not one of the Java Timer's.
I got curious enough to test it. Sourcecode:
public class Test {
public static Object returnObject() {
return new Object();
}
public static byte[] returnArray(){
return new byte[0];
}
}
Bytecode:
public static java.lang.Object returnObject();
Code:
0: new #2; //class java/lang/Object
3: dup
4: invokespecial #1; //Method java/lang/Object."<init>":()V
7: areturn
public static byte[] returnArray();
Code:
0: iconst_0
1: newarray byte
3: areturn
So you're right in that the byte code is shorter for arrays, because array creation has its own JVM opcode. But what does that mean? Nothing, really. It's a virtual machine, so there's absolutely no guarantee that fewer bytecode instructions mean less work for the actual physical CPU. We could start profiling of course, but that would be quite pointless. If there is a difference at all, no matter which way, it will never ever matter. Object creation is incredibly fast nowadays. You'd probably have to start using long
for your loop index before you can even measure the total time.
According to the Java Language Spec, "all class and array types inherit the methods of class Object", so I don't know how byte[0] could manage to be more efficient.
That seems to be true for the first edition of the spec as well: "The superclass of an array type is considered to be Object".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With