Frederick Tang Weblog

Stories about Oracle concepts I have learnt from work, and the occasional brain-dump…

Long road to loadjava…

with 5 comments


This week, one of my projects want to create some Java Stored Procedures in the Oracle9i database. The open source library their code uses is the Apache commons codec. To create the JSPs they wanted, I first have to load the codec library into the database. So the story starts…

1. Initially, I requested the development team to supply me with a Java 1.3 compiled Jar file of the codec library. This is because the Oracle JVM version in an Oracle9i database is 1.3. I was sent a Jar file that was compiled using a -target 1.3 flag, and when I tried to load this into the database:

$loadjava -u ftang/xxxxx -resolve commons-codec-1.3.jar

errors   : class org/apache/commons/codec/BinaryDecoder
    ORA-29534: referenced object org/apache/commons/codec/DecoderException could not be resolved
    ORA-29545: badly formed class:

…. <cut out most of the errors>

The following operations failed
    class org/apache/commons/codec/BinaryDecoder: resolution

…. <cut out most of the errors>

2. I then tried to use -genmissing flag, still no luck.

$loadjava -u ftang/xxxxx -genmissing commons-codec-1.3.jar

I didn’t get any errors in the Shell this time, but every Java Class shows INVALID as status in the database:

SQL> select object_name, object_type, status
  2  from user_objects
  3  where object_type like ‘%JAVA%’;

OBJECT_NAME                    OBJECT_TYPE        STATUS
—————————— —————— ——-
/1195a97a_BCodec               JAVA CLASS         INVALID
/26681f57_BinaryCodec          JAVA CLASS         INVALID
/2d100232_Encoder              JAVA CLASS         INVALID

…. <cut out the rest of the object names>

SQL> alter java class “/b6703010_EncoderException” resolve;

Warning: Java altered with compilation errors.

SQL> show errors
Errors for JAVA CLASS /b6703010_EncoderException:

LINE/COL ERROR
——– ————————————————
0/0      ORA-29545: badly formed class:

3. After a day of Metalink and Internet searching, I couldn’t figure out for the life of me why this is not working. I did read in a forum that suggested ORA-29545 is caused by incompatible Java Class file. In other words, Oracle JVM didn’t like the -target 1.3 compiled Jar file.

To test the truth, I downloaded the source code of the codec and compiled DecoderException.java using JDK 1.3.1_20:

$ java -version
java version “1.3.1_20”
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1_20-b03)
Java HotSpot(TM) Client VM (build 1.3.1_20-b03, mixed mode)

$ javac DecoderException.java

I then used Sundararajan’s Version.java to look at the differences:

$ java Version DecoderException.class
class file version is 45.3

$ java Version EncoderException.class
class file version is 47.0

$loadjava -u ftang/xxxxx DecoderException.class
$loadjava -u ftang/xxxxx EncoderException.class

SQL> select object_name, object_type, status
  2  from user_objects
  3  where object_type like ‘%JAVA%’;

OBJECT_NAME                    OBJECT_TYPE        STATUS
—————————— —————— ——-
/618456ed_DecoderException     JAVA CLASS         INVALID
/b6703010_EncoderException     JAVA CLASS         INVALID

SQL> alter java class “/618456ed_DecoderException” resolve;

Java altered.

SQL> alter java class “/b6703010_EncoderException” resolve;

Warning: Java altered with compilation errors.

SQL> show errors
Errors for JAVA CLASS /b6703010_EncoderException:

LINE/COL ERROR
——– ————————————————
0/0      ORA-29545: badly formed class:

SQL> select object_name, object_type, status
  2  from user_objects
  3  where object_type like ‘%JAVA%’;

OBJECT_NAME                    OBJECT_TYPE        STATUS
—————————— —————— ——-
/618456ed_DecoderException     JAVA CLASS         VALID
/b6703010_EncoderException     JAVA CLASS         INVALID

For example, the class file version and the corresponding JDK version is listed here.

So what this is telling at this stage, is that Oracle JVM didn’t like the class file version.

4. I then tried loading the entire source library into the database and see how it likes it. Perhaps if I let Oracle compile it, it might be happier.

$loadjava -u ftang/xxxxx commons-codec-1.3-src.zip

SQL> select object_name, object_type, status
  2  from user_objects
  3  where object_type like ‘%JAVA%’;

OBJECT_NAME                    OBJECT_TYPE        STATUS
—————————— —————— ——-
/1195a97a_BCodec               JAVA CLASS         INVALID
/1195a97a_BCodec               JAVA SOURCE        INVALID
/1de57d57_BCodecTest           JAVA CLASS         INVALID
/1de57d57_BCodecTest           JAVA SOURCE        INVALID
/1ecb3c26_QCodecTest           JAVA CLASS         INVALID
/1ecb3c26_QCodecTest           JAVA SOURCE        INVALID
/1f964432_BinaryCodecTest      JAVA CLASS         INVALID
/1f964432_BinaryCodecTest      JAVA SOURCE        INVALID
/26681f57_BinaryCodec          JAVA CLASS         INVALID
/26681f57_BinaryCodec          JAVA SOURCE        INVALID
/2d100232_Encoder              JAVA CLASS         INVALID
/2d100232_Encoder              JAVA SOURCE        INVALID
/2f584768_StringDecoder        JAVA CLASS         INVALID
/2f584768_StringDecoder        JAVA SOURCE        INVALID

The Java Source and Java Class now come in pairs, but are still INVALID. So I wrote a script to resolve all Java classes:

SQL> spool resolve.sql;

SQL> select ‘alter java class “‘||object_name||'” resolve;’
  2  from user_objects
  3  where object_type like ‘%JAVA%’;

SQL> spool off;

SQL> @resolve

Java altered.

Warning: Java altered with compilation errors.

Warning: Java altered with compilation errors.

Warning: Java altered with compilation errors.

Warning: Java altered with compilation errors.

Java altered.

Java altered.

… <cut out the rest of the output>

I have selected a few errors worth noting to paste below:

SQL> select name, type, text from user_errors;

/1de57d57_BCodecTest           JAVA CLASS
ORA-29535: source requires recompilation

/1de57d57_BCodecTest           JAVA SOURCE
org/apache/commons/codec/net/BCodecTest:22: Class junit.framework.TestCase not found in import.

/1de57d57_BCodecTest           JAVA SOURCE
org/apache/commons/codec/net/BCodecTest:29: Superclass junit.framework.TestCase of class org.apache.commons.codec.net.BCodecTest not found.

/1de57d57_BCodecTest           JAVA SOURCE
 Info: 2 errors

/26681f57_BinaryCodec          JAVA CLASS
ORA-29535: source requires recompilation

/26681f57_BinaryCodec          JAVA SOURCE
org/apache/commons/codec/binary/BinaryCodec:235: Incompatible type for =. Explicit cast needed to convert char to byte.

For example, BCodecTest is some JUnit test code, so there’s no need to make them work properly in the Oracle database. What’s worth noting is the error with BinaryCodec.

BinaryCodec Line 227: byte[] l_ascii = new byte[raw.length << 3];
BinaryCodec Line 235: l_ascii[jj – bits] = ‘0’;

It seems the compiler error is related to this: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4280591

QuotedPrintableCodec, BinaryCodec, URLCodec all have the same error reported by the Oracle Java Compiler. I guess to fix the error, I can cast the char to byte. However, the development team confirmed the classes will not be used, so we decided to not take any further actions.

Most of the Java Class are now valid:

SQL> select object_name, object_type, status
  2  from user_objects
  3  where object_type like ‘%JAVA%’;

OBJECT_NAME                    OBJECT_TYPE        STATUS
—————————— —————— ——-
/1195a97a_BCodec               JAVA CLASS         VALID
/1195a97a_BCodec               JAVA SOURCE        VALID
/1de57d57_BCodecTest           JAVA CLASS         INVALID
/1de57d57_BCodecTest           JAVA SOURCE        INVALID
/1ecb3c26_QCodecTest           JAVA CLASS         INVALID
/1ecb3c26_QCodecTest           JAVA SOURCE        INVALID
/1f964432_BinaryCodecTest      JAVA CLASS         INVALID
/1f964432_BinaryCodecTest      JAVA SOURCE        INVALID
/26681f57_BinaryCodec          JAVA CLASS         INVALID
/26681f57_BinaryCodec          JAVA SOURCE        INVALID
/2d100232_Encoder              JAVA CLASS         VALID
/2d100232_Encoder              JAVA SOURCE        VALID
/2f584768_StringDecoder        JAVA CLASS         VALID
/2f584768_StringDecoder        JAVA SOURCE        VALID

….

I guess this all could still be achieved just the same if we compile the source code into a Jar file, using a 1.3.x compiler.

To view long names of the Java Objects:

SQL> select dbms_java.longname(object_name)
  2  from user_objects where object_type like ‘%JAVA%’;

Hope this helps someone out there 🙂

Written by fredericktang

September 28, 2007 at 8:15 am

Posted in 9i, Java, Oracle

5 Responses

Subscribe to comments with RSS.

  1. Thanks, this is precisely what I was looking for. I just discovered the javaloader yesterday, and today was getting ready to start down the same road you described, in order to run classes with several dependencies. I think you just saved me several hours of mind-numbing analysis…I’ll let you know how it goes.

    Dane

    May 8, 2008 at 4:58 pm

  2. Hi Fredericktang,

    Thank you very much for this detailed post.
    Previously I was working on Oracle 10g, JUnit 4.4, JDK 1.5 combination.
    While loading the class file using “loadjava -verbose -user /@ -resolve “, it was showing me the same error “ORA-29545: badly formed class:”.

    Then I uninstalled JDK 1.5 and installed 1.4.2 and everything started working fine……..

    Thanks you again.

    -Regards,
    Saikat.

    Saikat

    May 27, 2008 at 11:52 am

  3. Hi Fredericktang,

    Thank you very much for this detailed post.
    Previously I was working on Oracle 10g, JUnit 4.4, JDK 1.5 combination.
    While loading the class file using “loadjava -verbose -user “User”/”Pass”@”Domain” -resolve “ClassName””, it was showing me the same error “ORA-29545: badly formed class:”.

    Then I uninstalled JDK 1.5 and installed 1.4.2 and everything started working fine……..

    Thanks you again.

    -Regards,
    Saikat.

    Saikat

    May 27, 2008 at 11:53 am

  4. Hi,

    Thanks for your sharing your experience through this posting. This helped me in solving the same type of issue which you have faced.

    Regards,
    Baksh.

    allahbaksh

    August 13, 2008 at 4:20 pm

  5. I think one of the solution is “directly” complie the java code in ORACLE sqlplus, that will for sure sync the diff. versions of JAVA compilers.

    john

    September 24, 2008 at 2:39 pm


Leave a comment