There are a number of concepts to tease apart:
- the Java programming language itself, which is a textual programming language,
- the Java Virtual Machine byte-code & class file format, which is a binary compiled encoding of original Java language source code, and is used as an interchange file format to store, load, and share java object code,
- a particular Java Virtual Machine implementation, which could be an interpreter though is often instead a JIT-based implementation,
- JIT generated machine code that runs directly on the hardware processor.
Java, the programming language, doesn't define a concept size of primitive types because (unlike C/C++) there is no
sizeof operator : sizes are not observable via language constructs, so the language doesn't need to define them.
As @Ralf points out the Java language does define the range of the primitive types, which is very relevant to the programmer as these ranges can be observed via constructs within the language.
The language does define an instrumentation capability that allows inquiry into the size of an object, but (1) this requires instrumentation, (2) provides only an estimate, and (3) this inquiry does not apply to primitive types or local variables.
the JVM uses a 32-bit stack cell, used to hold local variables, method arguments, and expression values. Primitives that are smaller than 1 cell are padded out, primitives larger than 32 bits (long and double) take 2 cells
The padding quote speaks to details of the JVM class file format, which is being used as an interchange mechanism (as distinct from the Java language and a JVM implementation). Though what it says holds for the abstract machine and JVM byte code, it does not necessarily have to hold for the JIT'ed machine code.
The padding quote also restricts itself to discussion of local variables/parameters/expressions that are typically stack allocated (e.g. auto or automatics in C/C++), and does not discuss object/arrays.
The actual size of such automatic variables is almost never an issue (e.g. for performance or for space).
In part, this is because the underlying hardware CPUs more naturally works on larger bit sizes (like 32 or 64) rather than 1-bit. Even 8 or 16 bit sizes are generally no faster than 32, and sometimes 8-bit handling requires an extra instruction or two to work with the hardware instruction set's wider registers.
And another reason is limited usage of local variables — they are used directly by code and only by code, and thus not really subject to scaling issues — in particular, as compared to objects and arrays, which are used by data structures of potentially any scale.
(We might consider recursion as scaling of local variables, so a larger local variables in recursive routines risks stack overflow sooner.)
However, sizes of objects can matter a lot, if the count of instances is high, and also, sizes of array elements can matter if having high number of elements.
Does it mean even byte/char/short primitiva data types also take 32 bit though their size is defined as 8/16/16 bit ?
For locals, maybe, maybe not depending on the JIT.
For objects, within the JVM byte code & class file mechanism, the fields are directly access by their identification and there is no notion given of "cells" — whereas there is with the (local and parameter) variables.
A JVM implementation (including its JIT) has the flexibility to rearrange field order within implementation (e.g. at the machine code level) so two 16-bit fields can occupy the same 32-bit word even if they were not declared adjacently in the source code; this reduces overhead caused by padding required to maintain alignment. Any such alighment, padding, and field placement are also very much JVM implementation-specific rather than JVM interchange format concerns. In theory, the JIT could pack booleans down to one-bit in an array, or pack 8 individual boolean fields into a single byte in an object. That most don't is a JVM implementation choice.