As I remember, the Dis bytecode used 64-bit instructions, with a 16 bit opcode, a 16-bit address and a 32-bit address. I've heard it described as a memory machine, and also as a machine with 65,536 registers.
In any case, it's easier and more efficient to perform register allocation from an intermediate language with a huge number of registers down to a small number of physical registers than it is to assign slot locations to registers. See Michael Franz's SafeTSA [1] project for an example of modifying a JVM to be able to mix and match both Java bytecode and an SSA-based bytecode in the same process. Granted SSA has some additional properties besides an infinite register set that make code generation nice. However, they found that it took less time to generate native code from SafeTSA and that the generated native code ran faster, even though the JIT backend was identical for the two bytecode formats. The disadvantage of SSA and memory machine bytecodes is they are more complicated to efficiently interpret if you're not generating native code from them.
The right way to look at Java's bytecode stream is opcodes for a register machine with _implicit_ input and output registers. Mapping it to a compiler IR would not be easy in the general case if that weren't true.