OpenJPA
  1. OpenJPA
  2. OPENJPA-385

IndexOutOfBounds exception when parsing ".class" files

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.0.0, 1.0.1, 1.1.0
    • Fix Version/s: 1.0.1, 1.1.0
    • Component/s: lib
    • Labels:
      None

      Description

      When finding and parsing files via the classpath, we're hitting a situation where an invalid .class file is in the classpath. Although the files in question have the .class suffix, they do not have valid .class format. Not only are we blowing up via the serp utilities, but neither jad nor javap can recognize the files either. Here's the call stack that is produced:

      Exception in thread "main" java.lang.ClassFormatError: COM/ibm/db2os390/sqlj/custom/DB2SQLJCustomizer.class
      at org.apache.openjpa.lib.meta.ClassAnnotationMetaDataFilter.matches(ClassAnnotationMetaDataFilter.java:89)
      at org.apache.openjpa.lib.meta.ZipFileMetaDataIterator.hasNext(ZipFileMetaDataIterator.java:79)
      at org.apache.openjpa.lib.meta.MetaDataIteratorChain.hasNext(MetaDataIteratorChain.java:76)
      at org.apache.openjpa.lib.meta.ClassArgParser.mapTypeNames(ClassArgParser.java:277)
      at org.apache.openjpa.meta.AbstractCFMetaDataFactory.scan(AbstractCFMetaDataFactory.java:713)
      at org.apache.openjpa.meta.AbstractCFMetaDataFactory.getPersistentTypeNames(AbstractCFMetaDataFactory.java:583)
      at org.apache.openjpa.meta.MetaDataRepository.getPersistentTypeNames(MetaDataRepository.java:1190)
      at org.apache.openjpa.meta.MetaDataRepository.loadPersistentTypes(MetaDataRepository.java:1207)
      at org.apache.openjpa.jdbc.meta.MappingTool.run(MappingTool.java:1002)
      at org.apache.openjpa.jdbc.meta.MappingTool.run(MappingTool.java:977)
      at org.apache.openjpa.jdbc.meta.MappingTool.main(MappingTool.java:918)
      Caused by: java.lang.ArrayIndexOutOfBoundsException
      at serp.bytecode.lowlevel.ConstantPoolTable.readByte(ConstantPoolTable.java:106)
      at serp.bytecode.lowlevel.ConstantPoolTable.readUnsignedShort(ConstantPoolTable.java:114)
      at serp.bytecode.lowlevel.ConstantPoolTable.readUnsignedShort(ConstantPoolTable.java:184)
      at org.apache.openjpa.lib.meta.ClassAnnotationMetaDataFilter.matches(ClassAnnotationMetaDataFilter.java:67)
      ... 10 more

      As you can see, the file in question is actually coming from the db2jcc.jar. Although I could pursue why these files do not have the correct format, I'm proposing that we become more lenient in our "matches" logic. Right now, we are throwing this IOOB exception. This seems too harsh, especially since we just return "false" for any other indication that the resource is not an "interesting" class file with appropriate annotations. In my mind, this invalid class file should just be treated as if it didn't have the .class suffix.

      So, instead of the current exception throwing processing, I would like to change to just log a trace message. We already log an Info message for all of the files that we do process. And, logging an info message for a bad class format might just cause confusion (much like this exception throwing). Thus, I would like to just log a trace message with the appropriate information and return "false" on this matches() invocation.

      Any problems with this approach? I've looked at the caller's of this method and nobody is expecting to get the ClassFormatException or IOOB exception (unexpected runtime exception), so just logging and eating the exception and returning false looks safe.

      Kevin

      1. OPENJPA-385.patch
        3 kB
        Kevin Sutter
      2. OPENJPA-385.patch
        1 kB
        Kevin Sutter

        Activity

        Hide
        Kevin Sutter added a comment -

        Resolved via r580087 for both 1.0.1 and 1.1.0 releases.

        Show
        Kevin Sutter added a comment - Resolved via r580087 for both 1.0.1 and 1.1.0 releases.
        Hide
        Kevin Sutter added a comment -

        Updated version of the patch.

        Show
        Kevin Sutter added a comment - Updated version of the patch.
        Hide
        Kevin Sutter added a comment -

        Okay, so I didn't like the approach of just eating the exception and never logging the condition (just in case we have a problem with this area of the code). So, I found an easy way to set a log into the ClassAnnotationMetaDataFilter object when it gets created. Since this is a utility class, I didn't want to enforce a log file, so I will check for null before doing the logging. Here's what the logged message will look like if TRACE is turned on:

        812 MyBookJPA_annotation TRACE [main] openjpa.MetaData - Error extracting class information from "COM/ibm/db2os390/sqlj/custom/DB2SQLJCustomizer.class".
        java.lang.ClassFormatError: COM/ibm/db2os390/sqlj/custom/DB2SQLJCustomizer.class
        at org.apache.openjpa.lib.meta.ClassAnnotationMetaDataFilter.matches(ClassAnnotationMetaDataFilter.java:107)
        at org.apache.openjpa.lib.meta.ZipFileMetaDataIterator.hasNext(ZipFileMetaDataIterator.java:88)
        at org.apache.openjpa.lib.meta.MetaDataIteratorChain.hasNext(MetaDataIteratorChain.java:76)
        at org.apache.openjpa.lib.meta.ClassArgParser.mapTypeNames(ClassArgParser.java:282)
        at org.apache.openjpa.meta.AbstractCFMetaDataFactory.scan(AbstractCFMetaDataFactory.java:785)
        at org.apache.openjpa.meta.AbstractCFMetaDataFactory.getPersistentTypeNames(AbstractCFMetaDataFactory.java:608)
        at org.apache.openjpa.meta.MetaDataRepository.getPersistentTypeNames(MetaDataRepository.java:1214)
        at org.apache.openjpa.meta.MetaDataRepository.loadPersistentTypes(MetaDataRepository.java:1231)
        at org.apache.openjpa.jdbc.meta.MappingTool.run(MappingTool.java:1006)
        at org.apache.openjpa.jdbc.meta.MappingTool.run(MappingTool.java:980)
        at org.apache.openjpa.jdbc.meta.MappingTool.main(MappingTool.java:921)
        Caused by: java.lang.ArrayIndexOutOfBoundsException
        at serp.bytecode.lowlevel.ConstantPoolTable.readByte(ConstantPoolTable.java:81)
        at serp.bytecode.lowlevel.ConstantPoolTable.readUnsignedShort(ConstantPoolTable.java:88)
        at serp.bytecode.lowlevel.ConstantPoolTable.readUnsignedShort(ConstantPoolTable.java:153)
        at org.apache.openjpa.lib.meta.ClassAnnotationMetaDataFilter.matches(ClassAnnotationMetaDataFilter.java:79)
        ... 10 more

        I will post this new patch and plan to commit shortly...

        Kevin

        Show
        Kevin Sutter added a comment - Okay, so I didn't like the approach of just eating the exception and never logging the condition (just in case we have a problem with this area of the code). So, I found an easy way to set a log into the ClassAnnotationMetaDataFilter object when it gets created. Since this is a utility class, I didn't want to enforce a log file, so I will check for null before doing the logging. Here's what the logged message will look like if TRACE is turned on: 812 MyBookJPA_annotation TRACE [main] openjpa.MetaData - Error extracting class information from "COM/ibm/db2os390/sqlj/custom/DB2SQLJCustomizer.class". java.lang.ClassFormatError: COM/ibm/db2os390/sqlj/custom/DB2SQLJCustomizer.class at org.apache.openjpa.lib.meta.ClassAnnotationMetaDataFilter.matches(ClassAnnotationMetaDataFilter.java:107) at org.apache.openjpa.lib.meta.ZipFileMetaDataIterator.hasNext(ZipFileMetaDataIterator.java:88) at org.apache.openjpa.lib.meta.MetaDataIteratorChain.hasNext(MetaDataIteratorChain.java:76) at org.apache.openjpa.lib.meta.ClassArgParser.mapTypeNames(ClassArgParser.java:282) at org.apache.openjpa.meta.AbstractCFMetaDataFactory.scan(AbstractCFMetaDataFactory.java:785) at org.apache.openjpa.meta.AbstractCFMetaDataFactory.getPersistentTypeNames(AbstractCFMetaDataFactory.java:608) at org.apache.openjpa.meta.MetaDataRepository.getPersistentTypeNames(MetaDataRepository.java:1214) at org.apache.openjpa.meta.MetaDataRepository.loadPersistentTypes(MetaDataRepository.java:1231) at org.apache.openjpa.jdbc.meta.MappingTool.run(MappingTool.java:1006) at org.apache.openjpa.jdbc.meta.MappingTool.run(MappingTool.java:980) at org.apache.openjpa.jdbc.meta.MappingTool.main(MappingTool.java:921) Caused by: java.lang.ArrayIndexOutOfBoundsException at serp.bytecode.lowlevel.ConstantPoolTable.readByte(ConstantPoolTable.java:81) at serp.bytecode.lowlevel.ConstantPoolTable.readUnsignedShort(ConstantPoolTable.java:88) at serp.bytecode.lowlevel.ConstantPoolTable.readUnsignedShort(ConstantPoolTable.java:153) at org.apache.openjpa.lib.meta.ClassAnnotationMetaDataFilter.matches(ClassAnnotationMetaDataFilter.java:79) ... 10 more I will post this new patch and plan to commit shortly... Kevin
        Hide
        Kevin Sutter added a comment -

        Ran into a little snag with my proposal... All of this metadata processing code is in "lib" and "lib" doesn't have an associated configuration or logfactory, so I don't have a means to log the failing class name. I looked at alternatives of setting a configuration object on the ClassAnnotationMetaDataFilter, but that gets ugly real fast. And, for how much benefit? Since a malformed .class file is no better than a file that does not have the .class suffix, why not treat them the same? That is, just return "false" when we detect a malformed .class file? I would still put a comment in the code block indicating why we're eating the exception. I'll post a patch shortly so that you can see what I am referring to.

        Kevin

        Show
        Kevin Sutter added a comment - Ran into a little snag with my proposal... All of this metadata processing code is in "lib" and "lib" doesn't have an associated configuration or logfactory, so I don't have a means to log the failing class name. I looked at alternatives of setting a configuration object on the ClassAnnotationMetaDataFilter, but that gets ugly real fast. And, for how much benefit? Since a malformed .class file is no better than a file that does not have the .class suffix, why not treat them the same? That is, just return "false" when we detect a malformed .class file? I would still put a comment in the code block indicating why we're eating the exception. I'll post a patch shortly so that you can see what I am referring to. Kevin

          People

          • Assignee:
            Kevin Sutter
            Reporter:
            Kevin Sutter
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development