Hi, Robert.
The smallest integer on which JVM can operate is int. It can't store a "byte" on a stack or in a local variable. This behavior is reflected in JLS: all operators converts smaller types to an int (or greater types). You can't get a "byte" as a result of integer additions without a casting, for example.
And even when you pass byte to a method it is passed as an "int" on a JVM stack. When you cast something to a byte, result on a jvm stack will also be an integer. It will be truncated to a "byte" range, but still will be an integer. See i2b instruction. It sign-extends lower byte of the integer value.
You even may have two methods one accepting byte and other accepting integer. Both will receive it's argument as an integer on a stack. And the only difference will be in a method signature in an invocation instruction.
I am probably not understanding bipush, but why does it take the byte and convert it into an integer?
It is a matter of bytecode size. And it is completely unrelated with an actual type in a source. Java compiler may use bipush for bytes, characters, shorts and ints if they fits in a "byte" value range. If possible, compiler uses iconst_* instruction (1 byte). If it is not possible, compiler tries to use bipush (2 bytes). If it is also not possible (value is outside [-128,127] range), compilers tries to use sipush (3 bytes). If even this is not possible compiler uses LDC/LDCW with a pool index (2/3 bytes in bytecode + 5 bytes in a pool (and a constant pool's slot of course)).
No types, just a way to write integer (always an integer!) value using less bytes than in a general case.