• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Bytecode confusion

 
Greenhorn
Posts: 27
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi guys,

I am currently preparing for the OCAJ7 exam and am reviewing the material in Liguori's book which I recently finished. One test question involved adding a byte and a long, and, after some fiddling with javap (after a previous thread awared me of what it was) I noticed something strange was happening:



The code will output 100, but it's what happens in the bytecode breakdown that confuses me. This is the outcome from 'javap -v':



I am probably not understanding bipush, but why does it take the byte and convert it into an integer?

I found a nice list on wikipedia http://en.wikipedia.org/wiki/Java_bytecode_instruction_listings but I guess it hasn't helped my understanding. It says bipush involves pushing a byte onto the stack as an integer value - this reads to me like the byte is abandoned in favor of an integer, which seems to be the base level upon which calculations happen (iadd = add two integers, but there is no badd or sadd for byte or short). One nice thing I did see through bytecode instructions is that you can add any two primitives (aside from booleans of course) that you want in a println statement, and java will automatically convert them to the widest scoped variable in your sum. For instance, adding a byte and a long automatically converts the byte (now an integer) to a long via i2l, and then completes the sum via ladd (long add). This other bit confuses me though when they are both 'smaller' than an int but yet converted to an int anyway.
 
Ranch Hand
Posts: 121
12
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Robert Lippens
Greenhorn
Posts: 27
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Ah, I think I see now. I just checked by adding two shorts with a value of 100. Since this is within the range of a byte I expected bipush to be called, and indeed it was. Then, I changed those shorts values to 129 so that they would be just above the byte range, and sure enough sipush was used.

So it is not the calling of 'short' or 'byte' in my code that matters, it is the actual range of values byte, short, etc. can take. Even if an int is between -128 and 127 it will still get bipush-ed because it can be represented using 8 bits or less. Interesting!
 
No more fooling around. Read this tiny ad:
a bit of art, as a gift, that will fit in a stocking
https://gardener-gift.com
reply
    Bookmark Topic Watch Topic
  • New Topic