Is Byte implemented as Int anyway? - java

I had a java game book recommend implementing all data as Int when possible, that that type runs the fastest. It said the Byte, Char, and Boolean are implemented as Int anyway, so you don't save space and the casting you end up having to do in the code because of the Byte data will slow it down. For instance, a cast is needed for
a = (byte)(b+c);
since the addition result is an Int, even when a,b, and c are all declared as Bytes.
I currently have a huge 2D array declared as Byte for my game, to save space and for bitwise operations. Is it actually saving space? I've also seen bitwise operations done on Ints in examples, do bitwise operations work as expected on Ints?

This is generally incorrect. In fact, this is outlined in the JVM Specification §2.3:
The primitive data types supported by the Java Virtual Machine are the numeric types, the boolean type (§2.3.4), and the returnAddress type (§2.3.3).
The numeric types consist of the integral types (§2.3.1) and the floating-point types (§2.3.2).
The integral types are:
byte, whose values are 8-bit signed two's-complement integers, and whose default value is zero
short, whose values are 16-bit signed two's-complement integers, and whose default value is zero
int, whose values are 32-bit signed two's-complement integers, and whose default value is zero
long, whose values are 64-bit signed two's-complement integers, and whose default value is zero
char, whose values are 16-bit unsigned integers representing Unicode code points in the Basic Multilingual Plane, encoded with UTF-16, and whose default value is the null code point ('\u0000')
Now, for boolean it's slightly a different story. From §2.3.4:
Although the Java Virtual Machine defines a boolean type, it only provides very limited support for it. There are no Java Virtual Machine instructions solely dedicated to operations on boolean values. Instead, expressions in the Java programming language that operate on boolean values are compiled to use values of the Java Virtual Machine int data type.
You can see differences in the bytecode depending on whether you use a byte[] or an int[], so they're not identical:
byte[] b = {42};
ICONST_1
NEWARRAY T_BYTE
DUP
ICONST_0
BIPUSH 42
BASTORE
ASTORE 1
vs
int[] b = {42};
ICONST_1
NEWARRAY T_INT
DUP
ICONST_0
BIPUSH 42
IASTORE
ASTORE 1
Is it actually saving space?
Yes, it likely is, especially if the array is very large.
do bitwise operations work as expected on Ints?
Yes, they do.

It is true that byte + byte = int, requiring a cast, but bytes are implemented with 8 bits of data in memory, while ints are 32 bits. Therefore, using bytes will decrease the amount of memory that an array takes up by 4 times.
For example, if you had a 10 by 10 array of bytes, its size would be 800, but a 10 by 10 array of ints' size would be 3200.
More information on this

The answer depends on whether you are working with a single variable of type byte or with a byte array, byte[]. A byte array does indeed save space, with each Java byte using just a byte of memory (plus a constant amount of housekeeping data for the array object). However, a single local variable of type byte is actually stored as an int on the stack and takes the corresponding 4 bytes of memory. This is even expressed in the bytecode - there is the opcode baload - "Load byte or boolean from array" but there is no opcode for loading a byte from local variable like there is iload for ints. Similarily, local char and boolean variables actually are stored on the stack as an int and int-based opcodes are used to access them.
The entry 2.6.1 in JLS also says that all local variables take either one or two "slots" on the stack, so the single-slot types byte, char, float and int all take the same space. The JVM cannot address a unit smaller than a single such slot, so in the case of a byte, 3 bytes are so to say wasted.
To wrap it up: do use byte arrays to save space, but in the case of individual variables, using a byte instead of int won't save space and may even have a small negative performance impact (it may however be required if you need byte for the semantics, e.g. counter wrapping behavior and such).

Yes, when you perform a byte addition the return value is always an integer, reason being that 8bit + 8bit addition can always result in a value which is greater than 8bit.
e.g.
decimal | binary
255 | 1111 1111
121 | 0111 1001
376 | 1 0111 1000
So if you try to store it in a byte again will definitely result in loss of data.
Instead of 376 you would get "120" if typecasting to byte is done.
You can definitely use int instead of byte and also the bit wise operations work perfectly on int.
refer: http://www.tutorialspoint.com/java/java_bitwise_operators_examples.htm

Related

I have to cast the first two octets from int to byte but not the other octets. Why?

byte[] ipAddr = new byte[] {(byte) 142, (byte) 250,68,46};
I am getting to know the various java net functions and I have to cast the first two octets to a byte in order for it to compile.
Otherwise I get this error
java: incompatible types: possible lossy conversion from int to byte
Any idea why I have to cast specifically the first octets and not all? Why does java take it as an int instead of a byte?
In java, bytes are 8-bit signed datatypes, so the value ranges from -128 to +127. Your first two values are greater than the maximum so you need to manually allow the conversion (by casting, in your case).
Those two octets just happen to be larger than the maximum value allowed in a byte which is 127 (2^7-1). Any value greater than 127 will have to be cast (or dealt with more carefully) and you'll lose data in a straight cast due to the size difference. See here for more: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html#:~:text=Primitive%20values%20do%20not%20share,value%20of%20127%20(inclusive).
#Dennis is on the right track, but the explanation is a bit more complicated than that.
Normally, an int valued expression cannot be assigned to a byte variable without a cast.
When the int valued expression is a constant expression, AND when the value of the expression is within the range of byte, then the assignment to a byte variable is allowed without a cast.
However, this only applies in assignment contexts, and only for constant expressions that satisfy the JLS definition.
In your example, the integer literals are all constant expressions, but the first two are not in the required range for lossless assignment ot a byte; i.e -128 to +127.

Java - indexing into array with a byte

Is it possible to index a Java array based on a byte?
i.e. something like
array[byte b] = x;
I have a very performance-critical application which reads b (in the code above) from a file, and I don't want the overhead of converting this to an int. What is the best way to achieve this? Is there a performance-decrease as a result of using this method of indexing rather than an int?
With many thanks,
Froskoy.
There's no overhead for "converting this to an int." At the Java bytecode level, all bytes are already ints.
In any event, doing array indexing will automatically upcast to an int anyway. None of these things will improve performance, and many will decrease performance. Just leave your code using an int.
The JVM specification, section 2.11.1:
Note that most instructions in Table 2.2 do not have forms for the integral types byte, char, and short. None have forms for the boolean type. Compilers encode loads of literal values of types byte and short using Java virtual machine instructions that sign-extend those values to values of type int at compile-time or runtime. Loads of literal values of types boolean and char are encoded using instructions that zero-extend the literal to a value of type int at compile-time or runtime. Likewise, loads from arrays of values of type boolean, byte, short, and char are encoded using Java virtual machine instructions that sign-extend or zero-extend the values to values of type int. Thus, most operations on values of actual types boolean, byte, char, and short are correctly performed by instructions operating on values of computational type int.
As all integer types in java are signed you have anyway to mask out 8 bits of b's value provided you do expect to read from the file values greater than 0x7F:
byte b;
byte a[256];
a [b & 0xFF] = x;
No; array indices are non-negative integers (JLS 10.4), but byte indices will be promoted.
No, there is no performance decrease, because on the moment you read the byte, you store it in a CPU register sometime. Those registers always works with WORDs, which means that the byte is always "converted" to an int (or a long, if you are on a 64 bit machine).
So, simply read your byte like this:
int b = (in.readByte() & 0xFF);
If your application is that performance critical, you should be optimizing elsewhere.

'byte' type in Java [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Literal Syntax For byte[] arrays using Hex notation..?
I am trying to create a byte array of size '1' that holds the byte 0x0. In Java, can I just do something like this:
byte[] space = new byte[1];
space[0] = 0x0;
Will the hex value 0x0 be converted to its byte rep of 00000000 and store it in space[0]?
Will the hex value 0x0 be converted to its byte rep of 00000000 and store it in space[0]?
In your executing program, there is only one representation of the Java byte value zero - the 8 bit 2's complement representation of the integer zero - 8 zero bits.
It doesn't make any difference whether you express the number literal in your source code as 0 (decimal) or 00 (octal) or 0x0. They all mean exactly the same thing.
So - Yes, your code does what you expect.
A simpler one line version would be:
byte[] space = new byte[] {0};
or
byte[] space = {0};
or even
byte[] space = new byte[1];
(The last one relies on the fact that Java byte arrays are default initialized to all zeros.)
Will the hex value 0x0 be converted to its byte rep of 00000000 and store it in space[0]?
Sort of yes. Technically (i.e. according to the JLS) what happens is this:
0x0 becomes an int literal. (The specific syntax used for the integer literal is actually immaterial at this point ... so long as it is valid.)
The int literal is narrowed using an implicit primitive narrowing conversion to a byte value.
The byte value is used in the initialization of the array.
The implicit narrowing in step 2 is allowed because:
This is in an assignment context.
The value being assigned is a compile time constant expression of an integer type. (A literal is a compile time constant expression.)
The actual value being assigned is in the range of the type it is to be assigned to. (In this case, -128 to +127.)
In layman's terms, the compiler "knows" that there will never be any loss of information in the narrowing conversion.
Yes this will do exactly what you think it should do. Also see this related question.

Integer vs int: with regard to memory

I was wondering if there is a difference in the memory occupied by
Integer n, and int n.
I know int n occupies 4 bytes normally, how about Integer n
In general, the heap memory used by a Java object in Hotspot consists of:
an object header, consisting of a few bytes of "housekeeping" information;
memory for primitive fields, according to their size (int n->32 bits)
memory for reference fields (4 bytes each) (Integer n ->32 bits)
padding: potentially a few "wasted" unused bytes after the object data, to make every object start at an address that is a convenient multiple of bytes and reduce the number of bits required to represent a pointer to an object.
as per the suggestion of Mark Peters I would like add the link below
http://www.javamex.com/tutorials/memory/object_memory_usage.shtml
An Integer object in Java occupies 16 bytes.
I don't know whether running a 64- vs 32-bit JVM makes a difference. For primitive types, it does not matter. But I can not say for certain how the memory footprint of an object changes (if at all) under a 64-bit system.
You can test this for yourself here:
Java Tip 130: Do you know your data size?
int is a primitive data type which takes 32 bits(4 bytes) to store.
When your Java code uses the new operator to create an instance of a Java object, much more
data is allocated than you might expect.
For example, it might surprise you to know that the size ratio of an int value to an Integer object — the smallest object that can hold an int value — is
typically 1:4.
Integer is an object which takes 128 bits (16 bytes) to store int value.
When we creates new Integer using new Operator it allocates memory as per follows.
Class Object(32 bits) - which consist of a pointer to the class information, which describes the object in our case its point to java.lang.Integer class
Flags (32 bits)- It is collection of flags that describes the state of object.
Like is it has hash-code, is it array or not i.e. its Shape.
Lock (32 bits) - It stores synchronization information of object. whether the object currently synchronized or not.
Above 3 points are called as metadata of an Object.
Lastly metadata is followed by the Object data (32 bits) itself. In case of Integer its single int value.
All the above explanation is as per 32 bit processor architecture. It can differ from JVM version and vendor.
For int: 4 bytes used per element without wrappers, and 16 per element with a wrapper.
A wrapped double reports as 24 bytes per element, with the actual double value as 64 bits (8 bytes).
For more details here

When casting a small integer type to a wider one, is it safe to rely on &ing with a mask to remove the sign?

I have code that stores values in the range 0..255 in a Java byte to save space in large data collections (10^9 records spread over a couple hundred arrays).
Without additional measures on recovery, the larger values are interpreted as being negative (because the Java integer types use two's complement representation).
I got this helpful hint from starblue in response to a related question, and I'm wondering if this technique is safe to rely on:
int iOriginal = 128, iRestore;
byte bStore = (byte) iOriginal; // reading this value directly would yield -128
iRestore = 0xff & bStore;
Yes, it's safe, indeed it's the most effective way of converting a byte into an (effectively) unsigned integer.
The byte half of the and operation will be sign-extended to an int, i.e. whatever was in bit 7 will be expanded into bits 8-31.
Masking off the bottom eight bits (i.e. & 0xff) then gives you an int that has zero in every bit from 8 - 31, and must therefore be in the range 0 ... 255.
See a related answer I gave here.

Categories