Targeting Specific Java Versions (and using javap)
I recently worked on a project where it became necessary to determine the version of the compiler that individual class files were compiled with. More specifically, I needed to determine the target version of Java the code was compiled to run on. You need to be specific about that since even the Java SE 6 compiler can be made to compile classes specifically for other versions of Java.
Compiled from "AccountClient.java"
public class AccountClient extends java.lang.Object
SourceFile: "AccountClient.java"
minor version: 0
major version: 48
Constant pool:
const #1 = Method #32.#41; // java/lang/Object."":()V
const #2 = class #42; // java/rmi/RMISecurityManager
const #3 = Method #2.#41; // java/rmi/RMISecurityManager."":()V
const #4 = Method #43.#44; // java/lang/System.setSecurityManager:(Ljava/lang/SecurityManager;)V
const #5 = String #45; // rmi://localhost/Account
const #6 = Method #46.#47; // java/rmi/Naming.lookup:(Ljava/lang/String;)Ljava/rmi/Remote;
const #7 = class #48; // Account
const #8 = float 12000.0f;
const #9 = InterfaceMethod #7.#49; // Account.deposit:(F)V
const #10 = Field #43.#50; // java/lang/System.out:Ljava/io/PrintStream;
const #11 = class #51; // java/lang/StringBuffer
const #12 = Method #11.#41; // java/lang/StringBuffer."":()V
const #13 = String #52; // Deposited 12,000 into account owned by
const #14 = Method #11.#53; // java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
const #15 = InterfaceMethod #7.#54; // Account.getName:()Ljava/lang/String;
const #16 = Method #11.#55; // java/lang/StringBuffer.toString:()Ljava/lang/String;
const #17 = Method #56.#57; // java/io/PrintStream.println:(Ljava/lang/String;)V
const #18 = String #58; // Balance now totals:
const #19 = InterfaceMethod #7.#59; // Account.getBalance:()F
const #20 = Method #11.#60; // java/lang/StringBuffer.append:(F)Ljava/lang/StringBuffer;
const #21 = class #61; // java/rmi/RemoteException
const #22 = Field #43.#62; // java/lang/System.err:Ljava/io/PrintStream;
const #23 = String #63; // Remote exception while looking up account:
const #24 = Method #21.#64; // java/rmi/RemoteException.getMessage:()Ljava/lang/String;
const #25 = class #65; // java/rmi/NotBoundException
const #26 = String #66; // Server object not found at expected URL:
const #27 = Method #25.#64; // java/rmi/NotBoundException.getMessage:()Ljava/lang/String;
const #28 = class #67; // java/net/MalformedURLException
const #29 = String #68; // Bad RMI URL given for server object:
const #30 = Method #28.#64; // java/net/MalformedURLException.getMessage:()Ljava/lang/String;
const #31 = class #69; // AccountClient
const #32 = class #70; // java/lang/Object
const #33 = Asciz ;
const #34 = Asciz ()V;
const #35 = Asciz Code;
const #36 = Asciz LineNumberTable;
const #37 = Asciz main;
const #38 = Asciz ([Ljava/lang/String;)V;
const #39 = Asciz SourceFile;
const #40 = Asciz AccountClient.java;
const #41 = NameAndType #33:#34;// "":()V
const #42 = Asciz java/rmi/RMISecurityManager;
const #43 = class #71; // java/lang/System
const #44 = NameAndType #72:#73;// setSecurityManager:(Ljava/lang/SecurityManager;)V
const #45 = Asciz rmi://localhost/Account;
const #46 = class #74; // java/rmi/Naming
const #47 = NameAndType #75:#76;// lookup:(Ljava/lang/String;)Ljava/rmi/Remote;
const #48 = Asciz Account;
const #49 = NameAndType #77:#78;// deposit:(F)V
const #50 = NameAndType #79:#80;// out:Ljava/io/PrintStream;
const #51 = Asciz java/lang/StringBuffer;
const #52 = Asciz Deposited 12,000 into account owned by ;
const #53 = NameAndType #81:#82;// append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
const #54 = NameAndType #83:#84;// getName:()Ljava/lang/String;
const #55 = NameAndType #85:#84;// toString:()Ljava/lang/String;
const #56 = class #86; // java/io/PrintStream
const #57 = NameAndType #87:#88;// println:(Ljava/lang/String;)V
const #58 = Asciz Balance now totals: ;
const #59 = NameAndType #89:#90;// getBalance:()F
const #60 = NameAndType #81:#91;// append:(F)Ljava/lang/StringBuffer;
const #61 = Asciz java/rmi/RemoteException;
const #62 = NameAndType #92:#80;// err:Ljava/io/PrintStream;
const #63 = Asciz Remote exception while looking up account: ;
const #64 = NameAndType #93:#84;// getMessage:()Ljava/lang/String;
const #65 = Asciz java/rmi/NotBoundException;
const #66 = Asciz Server object not found at expected URL: ;
const #67 = Asciz java/net/MalformedURLException;
const #68 = Asciz Bad RMI URL given for server object: ;
const #69 = Asciz AccountClient;
const #70 = Asciz java/lang/Object;
const #71 = Asciz java/lang/System;
const #72 = Asciz setSecurityManager;
const #73 = Asciz (Ljava/lang/SecurityManager;)V;
const #74 = Asciz java/rmi/Naming;
const #75 = Asciz lookup;
const #76 = Asciz (Ljava/lang/String;)Ljava/rmi/Remote;;
const #77 = Asciz deposit;
const #78 = Asciz (F)V;
const #79 = Asciz out;
const #80 = Asciz Ljava/io/PrintStream;;
const #81 = Asciz append;
const #82 = Asciz (Ljava/lang/String;)Ljava/lang/StringBuffer;;
const #83 = Asciz getName;
const #84 = Asciz ()Ljava/lang/String;;
const #85 = Asciz toString;
const #86 = Asciz java/io/PrintStream;
const #87 = Asciz println;
const #88 = Asciz (Ljava/lang/String;)V;
const #89 = Asciz getBalance;
const #90 = Asciz ()F;
const #91 = Asciz (F)Ljava/lang/StringBuffer;;
const #92 = Asciz err;
const #93 = Asciz getMessage;
{
public AccountClient();
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: invokespecial #1; //Method java/lang/Object."":()V
4: return
LineNumberTable:
line 11: 0
public static void main(java.lang.String[]);
Code:
Stack=3, Locals=2, Args_size=1
0: new #2; //class java/rmi/RMISecurityManager
3: dup
4: invokespecial #3; //Method java/rmi/RMISecurityManager."":()V
7: invokestatic #4; //Method java/lang/System.setSecurityManager:(Ljava/lang/SecurityManager;)V
10: ldc #5; //String rmi://localhost/Account
12: invokestatic #6; //Method java/rmi/Naming.lookup:(Ljava/lang/String;)Ljava/rmi/Remote;
15: checkcast #7; //class Account
18: astore_1
19: aload_1
20: ldc #8; //float 12000.0f
22: invokeinterface #9, 2; //InterfaceMethod Account.deposit:(F)V
27: getstatic #10; //Field java/lang/System.out:Ljava/io/PrintStream;
30: new #11; //class java/lang/StringBuffer
33: dup
34: invokespecial #12; //Method java/lang/StringBuffer."":()V
37: ldc #13; //String Deposited 12,000 into account owned by
39: invokevirtual #14; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
42: aload_1
43: invokeinterface #15, 1; //InterfaceMethod Account.getName:()Ljava/lang/String;
48: invokevirtual #14; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
51: invokevirtual #16; //Method java/lang/StringBuffer.toString:()Ljava/lang/String;
54: invokevirtual #17; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
57: getstatic #10; //Field java/lang/System.out:Ljava/io/PrintStream;
60: new #11; //class java/lang/StringBuffer
63: dup
64: invokespecial #12; //Method java/lang/StringBuffer."":()V
67: ldc #18; //String Balance now totals:
69: invokevirtual #14; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
72: aload_1
73: invokeinterface #19, 1; //InterfaceMethod Account.getBalance:()F
78: invokevirtual #20; //Method java/lang/StringBuffer.append:(F)Ljava/lang/StringBuffer;
81: invokevirtual #16; //Method java/lang/StringBuffer.toString:()Ljava/lang/String;
84: invokevirtual #17; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
87: goto 183
90: astore_1
91: getstatic #22; //Field java/lang/System.err:Ljava/io/PrintStream;
94: new #11; //class java/lang/StringBuffer
97: dup
98: invokespecial #12; //Method java/lang/StringBuffer."":()V
101: ldc #23; //String Remote exception while looking up account:
103: invokevirtual #14; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
106: aload_1
107: invokevirtual #24; //Method java/rmi/RemoteException.getMessage:()Ljava/lang/String;
110: invokevirtual #14; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
113: invokevirtual #16; //Method java/lang/StringBuffer.toString:()Ljava/lang/String;
116: invokevirtual #17; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
119: goto 183
122: astore_1
123: getstatic #22; //Field java/lang/System.err:Ljava/io/PrintStream;
126: new #11; //class java/lang/StringBuffer
129: dup
130: invokespecial #12; //Method java/lang/StringBuffer."":()V
133: ldc #26; //String Server object not found at expected URL:
135: invokevirtual #14; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
138: aload_1
139: invokevirtual #27; //Method java/rmi/NotBoundException.getMessage:()Ljava/lang/String;
142: invokevirtual #14; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
145: invokevirtual #16; //Method java/lang/StringBuffer.toString:()Ljava/lang/String;
148: invokevirtual #17; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
151: goto 183
154: astore_1
155: getstatic #22; //Field java/lang/System.err:Ljava/io/PrintStream;
158: new #11; //class java/lang/StringBuffer
161: dup
162: invokespecial #12; //Method java/lang/StringBuffer."":()V
165: ldc #29; //String Bad RMI URL given for server object:
167: invokevirtual #14; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
170: aload_1
171: invokevirtual #30; //Method java/net/MalformedURLException.getMessage:()Ljava/lang/String;
174: invokevirtual #14; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
177: invokevirtual #16; //Method java/lang/StringBuffer.toString:()Ljava/lang/String;
180: invokevirtual #17; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
183: return
Exception table:
from to target type
0 87 90 Class java/rmi/RemoteException
0 87 122 Class java/rmi/NotBoundException
0 87 154 Class java/net/MalformedURLException
LineNumberTable:
line 15: 0
line 18: 10
line 21: 19
line 24: 27
line 26: 57
line 39: 87
line 28: 90
line 29: 91
line 39: 119
line 32: 122
line 33: 123
line 39: 151
line 36: 154
line 37: 155
line 40: 183
}

