Java News Brief
February 2000 Issue
Headlines:
Java Technical Insight of the Month - Inside the Java
Virtual Machine
Visit The Java News Brief
Archive for past issues of the JNB.
OCI
Education Center - Open Enrollment Schedule
Java
Technical Insight of the Month
What is the
Java Virtual Machine?
By Ernest Rider, Senior Software
Engineer, Object Computing, Inc.
The Java
Virtual Machine (JVM), is the Sun Microsystems specification of a
(emulated) virtual 32 bit processor, that directly supports the Java
programming language. The JVM executes operating system and hardware
independent binary format bytecodes. JVM's can currently execute 254
different types of "bytecodes" (virtual machine instructions). Each
bytecode is exactly one byte (8 bits). (bytecode 186 are unused)
What do bytecodes look like?
Well, they are all in binary format as we might expect. Bytecodes exists to manipulate primitive types (byte, short, int, long, char, float, double, boolean, and JVM internal return address types) and reference types (Objects/Arrays).
All bytecodes look like this:
mnemonic
<operand1>, <operand2>, ...... e.g. fadd
where mnemonic can be one of the pseudo codes in the table below:
|
bytecode |
bytecode (Hex) |
Pseudo Code (Sun's Format) |
bytecode |
bytecode (Hex) |
Pseudo Code (Sun's Format) |
bytecode |
bytecode (Hex) |
Pseudo Code (Sun's Format) |
|---|---|---|---|---|---|---|---|---|
|
0 |
(0x00) |
nop |
86 |
(0x56) |
sastore |
171 |
(0xab) |
lookupswitch |
|
1 |
(0x01) |
aconst_null |
87 |
(0x57) |
pop |
172 |
(0xac) |
ireturn |
|
2 |
(0x02) |
iconst_m1 |
88 |
(0x58) |
pop2 |
173 |
(0xad) |
lreturn |
|
3 |
(0x03) |
iconst_0 |
89 |
(0x59) |
dup |
174 |
(0xae) |
freturn |
|
4 |
(0x04) |
iconst_1 |
90 |
(0x5a) |
dup_x1 |
175 |
(0xaf) |
dreturn |
|
5 |
(0x05) |
iconst_2 |
91 |
(0x5b) |
dup_x2 |
176 |
(0xb0) |
areturn |
|
6 |
(0x06) |
iconst_3 |
92 |
(0x5c) |
dup2 |
177 |
(0xb1) |
return |
|
7 |
(0x07) |
iconst_4 |
93 |
(0x5d) |
dup2_x1 |
178 |
(0xb2) |
getstatic |
|
8 |
(0x08) |
iconst_5 |
94 |
(0x5e) |
dup2_x2 |
179 |
(0xb3) |
putstatic |
|
9 |
(0x09) |
lconst_0 |
95 |
(0x5f) |
swap |
180 |
(0xb4) |
getfield |
|
10 |
(0x0a) |
lconst_1 |
96 |
(0x60) |
iadd |
181 |
(0xb5) |
putfield |
|
11 |
(0x0b) |
fconst_0 |
97 |
(0x61) |
ladd |
182 |
(0xb6) |
invokevirtual |
|
12 |
(0x0c) |
fconst_1 |
98 |
(0x62) |
fadd |
183 |
(0xb7) |
invokespecial |
|
13 |
(0x0d) |
fconst_2 |
99 |
(0x63) |
dadd |
184 |
(0xb8) |
invokestatic |
|
14 |
(0x0e) |
dconst_0 |
100 |
(0x64) |
isub |
185 |
(0xb9) |
invokeinterface |
|
15 |
(0x0f) |
dconst_1 |
101 |
(0x65) |
lsub |
186 |
(0xba) |
xxxunusedxxx |
|
16 |
(0x10) |
bipush |
102 |
(0x66) |
fsub |
187 |
(0xbb) |
new |
|
17 |
(0x11) |
sipush |
103 |
(0x67) |
dsub |
188 |
(0xbc) |
newarray |
|
18 |
(0x12) |
ldc |
104 |
(0x68) |
imul |
189 |
(0xbd) |
anewarray |
|
19 |
(0x13) |
ldc_w |
105 |
(0x69) |
lmul |
190 |
(0xbe) |
arraylength |
|
20 |
(0x14) |
ldc2_w |
106 |
(0x6a) |
fmul |
191 |
(0xbf) |
athrow |
|
21 |
(0x15) |
iload |
107 |
(0x6b) |
dmul |
192 |
(0xc0) |
checkcast |
|
22 |
(0x16) |
lload |
108 |
(0x6c) |
idiv |
193 |
(0xc1) |
instanceof |
|
23 |
(0x17) |
fload |
109 |
(0x6d) |
ldiv |
194 |
(0xc2) |
monitorenter |
|
24 |
(0x18) |
dload |
100 |
(0x6e) |
fdiv |
195 |
(0xc3) |
monitorexit |
|
25 |
(0x19) |
aload |
111 |
(0x6f) |
ddiv |
196 |
(0xc4) |
wide |
|
26 |
(0x1a) |
iload_0 |
112 |
(0x70) |
irem |
197 |
(0xc5) |
multianewarray |
|
27 |
(0x1b) |
iload_1 |
113 |
(0x71) |
lrem |
198 |
(0xc6) |
ifnull |
|
28 |
(0x1c) |
iload_2 |
114 |
(0x72) |
frem |
199 |
(0xc7) |
ifnonnull |
|
29 |
(0x1d) |
iload_3 |
115 |
(0x73) |
drem |
200 |
(0xc8) |
goto_w |
|
30 |
(0x1e) |
lload_0 |
116 |
(0x74) |
ineg |
201 |
(0xc9) |
jsr_w |
|
31 |
(0x1f) |
lload_1 |
117 |
(0x75) |
lneg |
203 |
(0xcb) |
ldc_quick |
|
32 |
(0x20) |
lload_2 |
118 |
(0x76) |
fneg |
204 |
(0xcc) |
ldc_w_quick |
|
33 |
(0x21) |
lload_3 |
119 |
(0x77) |
dneg |
205 |
(0xcd) |
ldc2_w_quick |
|
34 |
(0x22) |
fload_0 |
120 |
(0x78) |
ishl |
206 |
(0xce) |
getfield_quick |
|
35 |
(0x23) |
fload_1 |
121 |
(0x79) |
lshl |
207 |
(0xcf) |
putfield_quick |
|
36 |
(0x24) |
fload_2 |
122 |
(0x7a) |
ishr |
208 |
(0xd0) |
getfield2_quick |
|
37 |
(0x25) |
fload_3 |
123 |
(0x7b) |
lshr |
209 |
(0xd1) |
putfield2_quick |
|
38 |
(0x26) |
dload_0 |
124 |
(0x7c) |
iushr |
210 |
(0xd2) |
getstatic_quick |
|
39 |
(0x27) |
dload_1 |
125 |
(0x7d) |
lushr |
211 |
(0xd3) |
putstatic_quick |
|
40 |
(0x28) |
dload_2 |
126 |
(0x7e) |
iand |
212 |
(0xd4) |
getstatic2_quick |
|
41 |
(0x29) |
dload_3 |
127 |
(0x7f) |
land |
213 |
(0xd5) |
putstatic2_quick |
|
42 |
(0x2a) |
aload_0 |
128 |
(0x80) |
ior |
214 |
(0xd6) |
invokevirtual_quick |
|
43 |
(0x2b) |
aload_1 |
129 |
(0x81) |
lor |
215 |
(0xd7) |
invokenonvirtual_quick |
|
44 |
(0x2c) |
aload_2 |
130 |
(0x82) |
ixor |
216 |
(0xd8) |
invokesuper_quick |
|
45 |
(0x2d) |
aload_3 |
131 |
(0x83) |
lxor |
217 |
(0xd9) |
invokestatic_quick |
|
46 |
(0x2e) |
iaload |
132 |
(0x84) |
iinc |
218 |
(0xda) |
invokeinterface_quick |
|
47 |
(0x2f) |
laload |
133 |
(0x85) |
i2l |
219 |
(0xdb) |
invokevirtualobject_quick |
|
48 |
(0x30) |
faload |
134 |
(0x86) |
i2f |
221 |
(0xdd) |
new_quick |
|
49 |
(0x31) |
daload |
135 |
(0x87) |
i2d |
222 |
(0xde) |
anewarray_quick |
|
50 |
(0x32) |
aaload |
136 |
(0x88) |
l2i |
223 |
(0xdf) |
multianewarray_quick |
|
51 |
(0x33) |
baload |
137 |
(0x89) |
l2f |
224 |
(0xe0) |
checkcast_quick |
|
52 |
(0x34) |
caload |
138 |
(0x8a) |
l2d |
225 |
(0xe1) |
instanceof_quick |
|
53 |
(0x35) |
saload |
139 |
(0x8b) |
f2i |
226 |
(0xe2) |
invokevirtual_quick_w |
|
54 |
(0x36) |
istore |
140 |
(0x8c) |
f2l |
227 |
(0xe3) |
getfield_quick_w |
|
55 |
(0x37) |
lstore |
141 |
(0x8d) |
f2d |
228 |
(0xe4) |
putfield_quick_w |
|
56 |
(0x38) |
fstore |
142 |
(0x8e) |
d2i |
202 |
(0xca) |
breakpoint |
|
57 |
(0x39) |
dstore |
143 |
(0x8f) |
d2l |
254 |
(0xfe) |
impdep1 |
|
58 |
(0x3a) |
astore |
144 |
(0x90) |
d2f |
255 |
(0xff) |
impdep2 |
|
59 |
(0x3b) |
istore_0 |
145 |
(0x91) |
i2b |
|
|
|
|
60 |
(0x3c) |
istore_1 |
146 |
(0x92) |
i2c |
|
|
|
|
61 |
(0x3d) |
istore_2 |
147 |
(0x93) |
i2s |
|
|
|
|
62 |
(0x3e) |
istore_3 |
148 |
(0x94) |
lcmp |
|
|
|
|
63 |
(0x3f) |
lstore_0 |
149 |
(0x95) |
fcmpl |
|
|
|
|
64 |
(0x40) |
lstore_1 |
150 |
(0x96) |
fcmpg |
|
|
|
|
65 |
(0x41) |
lstore_2 |
151 |
(0x97) |
dcmpl |
|
|
|
|
66 |
(0x42) |
lstore_3 |
152 |
(0x98) |
dcmpg |
|
|
|
|
67 |
(0x43) |
fstore_0 |
153 |
(0x99) |
ifeq |
|
|
|
|
68 |
(0x44) |
fstore_1 |
154 |
(0x9a) |
ifne |
|
|
|
|
69 |
(0x45) |
fstore_2 |
155 |
(0x9b) |
iflt |
|
|
|
|
70 |
(0x46) |
fstore_3 |
156 |
(0x9c) |
ifge |
|
|
|
|
71 |
(0x47) |
dstore_0 |
157 |
(0x9d) |
ifgt |
|
|
|
|
72 |
(0x48) |
dstore_1 |
158 |
(0x9e) |
ifle |
|
|
|
|
73 |
(0x49) |
dstore_2 |
159 |
(0x9f) |
if_icmpeq |
|
|
|
|
74 |
(0x4a) |
dstore_3 |
160 |
(0xa0) |
if_icmpne |
|
|
|
|
75 |
(0x4b) |
astore_0 |
161 |
(0xa1) |
if_icmplt |
|
|
|
|
76 |
(0x4c) |
astore_1 |
162 |
(0xa2) |
if_icmpge |
|
|
|
|
77 |
(0x4d) |
astore_2 |
163 |
(0xa3) |
if_icmpgt |
|
|
|
|
78 |
(0x4e) |
astore_3 |
164 |
(0xa4) |
if_icmple |
|
|
|
|
79 |
(0x4f) |
iastore |
165 |
(0xa5) |
if_acmpeq |
|
|
|
|
80 |
(0x50) |
lastore |
166 |
(0xa6) |
if_acmpne |
|
|
|
|
81 |
(0x51) |
fastore |
167 |
(0xa7) |
goto |
|
|
|
|
82 |
(0x52) |
dastore |
168 |
(0xa8) |
jsr |
|
|
|
|
83 |
(0x53) |
aastore |
169 |
(0xa9) |
ret |
|
|
|
|
84 |
(0x54) |
bastore |
170 |
(0xaa) |
tableswitch |
|
|
|
|
85 |
(0x55) |
castore |
|
|
|
|
|
|
Can other languages produce
Java-byte code?
In Short. Yes!
bytecode Assembler: Jasmin, jas (http://www.sbktech.org/jas.html)
Pascal: University. Vrije Universiteit, Amsterdam, Netherlands.
Does this mean we don't have to write in Java to get "bytecode" portability? Well that's one for debate. All I can say is that you get the wealth of a pure object orientated language in Java; some of the best minds fixing/enhancing the technology, and some really nice frameworks that other languages are struggling to match. i.e. the Java Language embodies a design thought process, that is conducive to good OOP Practices.
What makes up a
JVM?
Example:
public class Person {
String name = "Unknown";
public void setName(String n) {
name = n;
}
public String getName() {
return(name);
}
public static void main(String args[]) {
Person p = new Person();
p.setName(args[0]);
System.out.println("The name of the person entered was "+p.getName()+".");
}
}
Using the command line java decompiler tool javap we can get the bytecode in pseudo ops ("-c") and the line numbers in the heap where they are stored ("-l").
C:\>javac Person.java
C:\>javap -c -l Person
Compiled from Person.java
public synchronized class Person extends java.lang.Object
/* ACC_SUPER bit set */
{
java.lang.String name;
public void setName(java.lang.String);
public java.lang.String getName();
public static void main(java.lang.String[]);
public Person();
}
Method void setName(java.lang.String)
0 aload_0
1 aload_1
2 putfield #14 -Field java.lang.String name-
5 return
Line numbers for method void setName(java.lang.String)
line 6: 0
line 5: 5
Method java.lang.String getName()
0 aload_0
1 getfield #14 -Field java.lang.String name-
4 areturn
Line numbers for method java.lang.String getName()
line 10: 0
Method void main(java.lang.String[])
0 new #4 -Class Person-
3 dup
4 invokespecial #9 -Method Person()-
7 astore_1
8 aload_1
9 aload_0
10 iconst_0
11 aaload
12 invokevirtual #17 -Method void setName(java.lang.String)-
15 getstatic #15 -Field java.io.PrintStream out-
18 new #7 -Class java.lang.StringBuffer-
21 dup
22 ldc #2 -String "The name of the person entered was "-
24 invokespecial #11 -Method java.lang.StringBuffer(java.lang.String)-
27 aload_1
28 invokevirtual #13 -Method java.lang.String getName()-
31 invokevirtual #12 -Method java.lang.StringBuffer append(java.lang.String)-
34 ldc #1 -String "."-
36 invokevirtual #12 -Method java.lang.StringBuffer append(java.lang.String)-
39 invokevirtual #18 -Method java.lang.String toString()-
42 invokevirtual #16 -Method void println(java.lang.String)-
45 return
Line numbers for method void main(java.lang.String[])
line 14: 0
line 15: 8
line 16: 15
line 13: 45
Method Person()
0 aload_0
1 invokespecial #10 -Method java.lang.Object()-
4 aload_0
5 ldc #3 -String "Unknown"-
7 putfield #14 -Field java.lang.String name-
10 return
Line numbers for method Person()
line 1: 0
line 3: 4
line 1: 10
Not very safe out-of-the-box. Many products exist to make the job of decompiling exponentially harder (closer to near impossible) through obfuscation. (obfuscate. To make so confused or opaque as to be difficult to perceive or understand)
An interesting article about finding similarities in
bytecode can be found at http://glimpse.cs.arizona.edu/javadup.html
Just like testing "real" machine performance, JVM performance is an open-ended battle. Claim and counter claim over who's has the best JVM could go on forever. This goes to show that computer people are very passionate people when it comes to issues such as performance.
"Performance means many things to many different applications."
So how do we meaningfully test performance? Well first you must accept that the 90/10 rule applies in general, i.e. 90% of the time is spent in 10% of the code, for a given unit. Then we must construct applications that typify our purpose or goal. Then we do some real time analysis. (Using a Java Thread to time ourselves is not good enough, as JVM's are for the most part, non-real time.) Fortunately the confusion over testing JVM performance has been confronted by the Java community. In an effort to gain a useful comparison of JVM's a set of application performance benchmarks have been adopted (sometimes to suite the implementor). It is very important that when using these tools the results have relevance to your needs. i.e. testing Thread performance may not give you great graphics.
Some useful ones:
| Name | Proprietor | Description |
| CaffieneMark 3.0 | Pendragon Software | |
| SpecJVM98 | Spec | http://www.spec.org/ |
| JMark | ZDNET | http://www.zdnet.com/zdbop/jmark/jmark.html |
| VolanoMark | volano | http://www.volano.com/benchmarks.html |
The future the Java Virtual Machine centers quite firmly -
around increasing its performance on any given architecture. Researchers and
developers will continue to peel away at its virtual'ness and add more and more
real machine code while keeping the bytecode source intact. Many different
architectures, and frameworks will be added to aid industry in making open
choices to technology. Hardware architectures that are bytecode compatible
are going to break performance ground earlier than software, but the holy grail
is the hybrid interpreted/native compiler. This will continue to be developed
and influence the ever increasing demand on performance software
technology.
OCI Education Center - Open Enrollment
Schedule
Mesa, Arizona - St. Louis,
Missouri
| Course Title | Facility | Dates | Hours |
| Using the ADAPTIVE Communication Environment C++ Framework | St. Louis | Mar 7-10 | 8:30-3:30 |
| CORBA Programming | Mesa | Mar 28-31 | 8:30-3:30 |
For more information or to register, email
training.
Object Computing, Inc. is a Sun Authorized Java Center in St. Louis and a Member of the Object Management Group, OMG. OCI specializes in distributed computing using object-oriented and web-enabled technologies and provides Consulting, Education, and Product Development services to clients nation-wide. For more information contact us at 314-579-0066 or email info.
For employment
opportunities at OCI call 1-888-962-4624 or email hr.
The Java News Brief is a monthly
newsletter. The purpose and intent of this publication is to advance Java,
provide technical value, and to announce available OCI Java services. If
you would prefer to not receive this newsletter or would like to subscribe
please email JNB and enter
SUBSCRIBE or UNSUBSCRIBE within the Subject line.
Copyright
(c) 2000. Object Computing, Inc. All rights reserved. Java
and all Java-based marks are trademarks or registered trademarks of Sun
Microsystems, Inc. in the United States and other countries. Object
Computing, Inc. is independent of Sun Microsystems,
Inc.