Attacking a Weird Java Error: java.lang.ClassFormatError: Invalid pc in line number table

While working on the Oracle Application Framework, my Application module’s class file was behaving in a strange manner. When it was deployed on Apache and run, it was throwing the following Error:


oracle.jbo.JboException: JBO-29000: Unexpected exception caught: java.lang.ClassFormatError, msg=oracle/apps/fnd/framework/test/updateAMImpl (Invalid pc in line number table)
at oracle.jbo.common.ampool.ApplicationPoolImpl.doCheckout(ApplicationPoolImpl.java:1619)
at oracle.jbo.common.ampool.ApplicationPoolImpl.useApplicationModule(ApplicationPoolImpl.java:2366)
at oracle.jbo.common.ampool.SessionCookieImpl.useApplicationModule(SessionCookieImpl.java:427)
at oracle.jbo.http.HttpSessionCookieImpl.useApplicationModule(HttpSessionCookieImpl.java:214)
at oracle.apps.fnd.framework.webui.OAHttpSessionCookieImpl.useApplicationModule(OAHttpSessionCookieImpl.java:473)
at oracle.jbo.common.ampool.SessionCookieImpl.useApplicationModule(SessionCookieImpl.java:398)

I Googled on this error a lot, but most of the suggested solutions spoke about compiling the class with a different JDK or a different Java version and deploying it again. I tried to do that, but the error persisted.

Decompiling using javap

I thought of decompiling the deployed class using the javap utility – if it would fail to decompile, that would surely indicate a problem with the class itself. However, javap decompiled it correctly, and correctly displayed public methods of the class.

I glanced through the help of javap (using -help), trying to figure out how to get a peek at the private methods too. While doing that, I noticed an interesting option: -verbose. This disassembles the code, and also prints the stack and line number table. Intrigued, I tried to run:

D:\JDeveloper\jdevhome\jdev\myclasses>javap -verbose oracle.apps.fnd.framework.test.UploadAMImpl > detailedclassUploadAMImpl

and it displayed the following (for the sake of brevity, I’ve pasted only relevant sections):


 170: invokestatic #92; //Method oracle/apps/fnd/framework/OAException.wrapperException:(Ljava/lang/Exception;)Loracle/apps/fnd/framework/OAException;
 173: athrow
 174: astore 11
 176: jsr 182
 179: aload 11
 181: athrow
 182: astore 12
 184: iload 7
 186: invokestatic #88; //Method java/lang/String.valueOf:(I)Ljava/lang/String;
 189: astore 8
 191: aload 8
 193: areturn
Exception table:
    from    to    target    type
   77   148   154   Class java/sql/SQLException

156 163 166 Class java/lang/Exception

77 174 174 any LineNumberTable: line 150: 0 line 151: 8 line 152: 14 line 153: 39 line 154: 58 line 155: 70 line 156: 73 line 158: 77 line 159: 86 line 160: 95 line 161: 104 line 162: 112 line 163: 122 line 164: 141 line 165: 154 line 167: 156 line 168: 166 line 169: 168 line 170: 174 line 171: 184 line 172: 191 line 174: 193 line 173: 194

Looking at the line number table and disassembled code, I didn’t get anything conclusive. Then I just tried the same stuff on another class which was not having the same problem:


D:\JDeveloper\jdevhome\jdev\myclasses>javap -verbose oracle.apps.fnd.framework.test.webui.testEmpCO
 > CODetailed

which gave me following output (again pasting relevant sections for sake of brevity)


 433: invokeinterface #28, 2; //InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
 438: checkcast #29; //class String
 441: astore 10
 443: aconst_null
 444: aload 9
 446: if_acmpeq 461
 449: aload_0
 450: aload_1
 451: aload_3
 452: aload 9
 454: aload 10
 456: aload 5
 458: invokespecial #79; //Method _triggerProcess:(Loracle/apps/fnd/framework/webui/OAPageContext;Loracle/apps/fnd/framework/OAApplicationModule;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
  461: return
 Exception table:
    from    to    target    type
    223    324    327    Class oracle/apps/fnd/framework/OAException

LineNumberTable: line 138: 0 line 140: 8 line 141: 14 line 142: 26 line 144: 34 line 145: 42 line 147: 52 line 148: 58 line 149: 73 line 150: 88 line 152: 107 line 153: 122 line 155: 133 line 156: 152 line 157: 171 line 158: 187 line 159: 206 line 161: 212 line 167: 223 line 168: 245 line 170: 254 line 171: 259 line 173: 274 line 175: 286 line 177: 300 line 178: 305 line 180: 316 line 185: 327 line 187: 329 line 188: 337 line 190: 346 line 191: 362 line 192: 375 line 193: 383 line 194: 391 line 196: 397 line 200: 411 line 201: 427 line 202: 443 line 203: 449 line 213: 461

I tried to compare the verbose output of both. Though I couldn’t make much out of it, I noticed one thing: for correct class (testEmpCO), the last line number in line number table (line 213: 461) against the last assembly instruction was same as the last line number of the disassembled code.(461: return)

However, for the class which had the error (UploadAMImpl), the last line in the line number table was 194 (line 173: 194). However the last line number for disassembled code was 193 (193: areturn). I became curious and checked the last assembly instruction which was starting at line 173 (pasted again below):


 170: invokestatic #92; //Method oracle/apps/fnd/framework/OAException.wrapperException:(Ljava/lang/Exception;)Loracle/apps/fnd/framework/OAException;
 173: athrow

Though I couldn’t decipher it completely, I could make out from instructions that it was something related to OAWrapperException, which was present in my code.

I decided to replace the same with OAException which is the normally followed practice instead of OAWrapperException, which I had copied from Fwk developer’s guide. After doing the change, I ran again


D:\JDeveloper\jdevhome\jdev\myclasses>javap -verbose oracle.apps.fnd.framework.test.UploadAMImpl >
AMDetailed.server

and the following was the output:


 195: invokespecial #32; //Method oracle/apps/fnd/framework/OAException."":(Ljava/lang/String;B)V
 198: athrow
 199: return
 Exception table:
    from    to    target    type
	   13    178    181    Class java/lang/Exception

LineNumberTable: line 106: 0 line 107: 8 line 109: 13 line 110: 20 line 112: 27 line 113: 43 line 114: 59 line 115: 74 line 116: 85 line 117: 104 line 118: 114 line 119: 130 line 120: 146 line 121: 162 line 123: 181 line 124: 182 line 125: 186 line 127: 199

Now, last line number in line number table 199 (line 127: 199) was matching with last line number of disassembled code ( 199: return). I hoped by now that this should work and after deploying, it really worked !!!!

I don’t know what was causing OAWrapperException to cause this issue , but I thought I would share this technique as this is generic error and it can be encountered by any java programmer. This is rare error and that is why it is difficult to address, as not lot of practical help is available on this and programmers can learn to unleash the power of javap and its various options.

I hope the technique I’ve described above will be handy for programmers who come across this kind of error.

Our guest writer, Vishal Chougule, is an avid Java developer and a technology lover. His interests range from computer security to design patterns.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>