You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@pdfbox.apache.org by Joel Hirsh <jo...@gmail.com> on 2018/08/01 15:42:03 UTC

PDFBox JPEG2000 and Tomcat - Revisited

I was having a problem a month ago with reading JPEG2000 files on tomcat,
that seemed identical to what is described in a posting to this list by
Chris Gamache <https://plus.google.com/u/0/101607728077454498498?prsrc=4>
 <cg...@gmail.com> on Jun 21 2017 with the subject "PDFBox JPEG2000 and
Tomcat".  Basically PDFBox was 'forgetting' about the JPEG2000 library at
some point, and getting an error when reading a JPEG2000 file.

I reached out to Chris and he was kind enough to offer me his solution,
which is to check for whether JPEG2000 is loaded before each call to
PDFBox, and then reload it.  And that seemed to resolve my problem.

I recently upgraded to PDFBox 2.0.11, and removed the library
levigo-jbig2-imageio-1.6.5.jar as those entry points were now being defined
in pdfbox-app-2.0.11.jar.

And what appears to be the same error is back.  Running one JPEG2000 image
is fine, but at some point I get the error

java.lang.NoClassDefFoundError: Could not initialize class
org.apache.pdfbox.jbig2.JBIG2ImageReader
  at
org.apache.pdfbox.jbig2.JBIG2ImageReaderSpi.createReaderInstance(JBIG2ImageReaderSpi.java:117)
  at
javax.imageio.spi.ImageReaderSpi.createReaderInstance(ImageReaderSpi.java:320)
  at javax.imageio.ImageIO$ImageReaderIterator.next(ImageIO.java:529)
  at javax.imageio.ImageIO$ImageReaderIterator.next(ImageIO.java:513)
  at org.apache.pdfbox.filter.Filter.findImageReader(Filter.java:155)
  at org.apache.pdfbox.filter.JBIG2Filter.decode(JBIG2Filter.java:67)
  at org.apache.pdfbox.cos.COSInputStream.create(COSInputStream.java:77)
  at org.apache.pdfbox.cos.COSStream.createInputStream(COSStream.java:175)
  at org.apache.pdfbox.cos.COSStream.createInputStream(COSStream.java:163)
  at
org.apache.pdfbox.pdmodel.common.PDStream.createInputStream(PDStream.java:236)
  at
org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject.createInputStream(PDImageXObject.java:695)
  at
org.apache.pdfbox.pdmodel.graphics.image.SampledImageReader.getStencilImage(SampledImageReader.java:91)
  at
org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject.getStencilImage(PDImageXObject.java:483)
  at org.apache.pdfbox.rendering.PageDrawer.drawImage(PageDrawer.java:1029)
  at
org.apache.pdfbox.contentstream.operator.graphics.DrawObject.process(DrawObject.java:62)
  at
org.apache.pdfbox.contentstream.PDFStreamEngine.processOperator(PDFStreamEngine.java:848)
  at
org.apache.pdfbox.contentstream.PDFStreamEngine.processStreamOperators(PDFStreamEngine.java:503)
  at
org.apache.pdfbox.contentstream.PDFStreamEngine.processStream(PDFStreamEngine.java:477)
  at
org.apache.pdfbox.contentstream.PDFStreamEngine.processPage(PDFStreamEngine.java:150)
  at org.apache.pdfbox.rendering.PageDrawer.drawPage(PageDrawer.java:246)
  at
org.apache.pdfbox.rendering.PDFRenderer.renderImage(PDFRenderer.java:225)
  at
org.apache.pdfbox.rendering.PDFRenderer.renderImageWithDPI(PDFRenderer.java:150)

Which is very similar to the error I got with PDFBox 2.0.7 and the levigo
jar

java.lang.NoClassDefFoundError: Could not initialize class
com.levigo.jbig2.JBIG2ImageReader
  at
com.levigo.jbig2.JBIG2ImageReaderSpi.createReaderInstance(JBIG2ImageReaderSpi.java:118)
  at
javax.imageio.spi.ImageReaderSpi.createReaderInstance(ImageReaderSpi.java:320)
  at javax.imageio.ImageIO$ImageReaderIterator.next(ImageIO.java:529)
  at javax.imageio.ImageIO$ImageReaderIterator.next(ImageIO.java:513)
  at org.apache.pdfbox.filter.Filter.findImageReader(Filter.java:120)
  at org.apache.pdfbox.filter.JBIG2Filter.decode(JBIG2Filter.java:54)
  at org.apache.pdfbox.cos.COSInputStream.create(COSInputStream.java:69)
  at org.apache.pdfbox.cos.COSStream.createInputStream(COSStream.java:167)
  at
org.apache.pdfbox.pdmodel.common.PDStream.createInputStream(PDStream.java:235)
  at
org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject.<init>(PDImageXObject.java:125)
  at
org.apache.pdfbox.pdmodel.graphics.PDXObject.createXObject(PDXObject.java:70)
  at org.apache.pdfbox.pdmodel.PDResources.getXObject(PDResources.java:409)
  at com.moneythumb.convert.i.processOperator(SourceFile:72)
  at
org.apache.pdfbox.contentstream.PDFStreamEngine.processStreamOperators(PDFStreamEngine.java:495)
  at
org.apache.pdfbox.contentstream.PDFStreamEngine.processStream(PDFStreamEngine.java:469)
  at
org.apache.pdfbox.contentstream.PDFStreamEngine.processPage(PDFStreamEngine.java:150)

Also the workaround from Chris was still in place, but did not appear to
help, although it is not specific to any packaging.  It checks whether the
reader for format 'JPEG2000' canReadRaster() and if not calls
IIORegistry.getDefaultInstance.registerApplicationClasspathSpis();.

So my take is that PDFBox inherited whatever problem was there previously
in the  JBIG2 ImageIO plugin.

And I am surprised that the workaround did not help - I assume the format
is still known at 'JPEG2000', right?

Re: PDFBox JPEG2000 and Tomcat - Revisited

Posted by Christopher Schultz <ch...@christopherschultz.net>.
Joel,

On 8/2/18 12:10 AM, Joel Hirsh wrote:
> Thanks for the explanation. I will look towards the tomcat mailing list.
> 
> Per your request about the entire stack trace - there is more above the
> first call to PDFBox, but the root cause in both cases is indeed
> "java.lang.NoClassDefFoundError:
> Could not initialize class".
> And I have seen that same error with other ClassLoader problems under
> Tomcat.

I understand, but there is a root-cause for "Could not initialize
class". Usually, it's something that fails unexpectedly in a static
initializer or something like that, and it should have its own separate
stack trace.

-chris

> On Wed, Aug 1, 2018 at 1:39 PM, Christopher Schultz <
> chris@christopherschultz.net> wrote:
> 
>> Joel,
>>
>> On 8/1/18 3:54 PM, Joel Hirsh wrote:
>>> However, your comment that "Tomcat doesn't unload libraries" is not
>>> entirely true. There is an explanation of such symptions at
>>> https://haraldk.github.io/TwelveMonkeys/, under the section "Deploying
>> the
>>> plugins in a web app".
>>
>> Thanks for posting that. Lemmie 'splain.
>>
>> In a servlet container, web applications (aka "contexts") each have
>> their own ClassLoader and if the application is undeployed or
>> re-deployed, then that ClassLoader will be freed for GC. If a class
>> loaded by that webapp's ClassLoader is still in use, you have a memory
>> leak situation knows as a "pinned ClassLoader".
>>
>> It happens all the time when you use a system-global cache such as
>> ImageIO does. This can happen with JDBC DriverManger and a handful of
>> other common APIs and it can be a serious problem for servers where
>> there are lots of redeployments. You can also start to see errors like
>> "ClassCastException: Cannot cast foo.bar.Class to foo.bar.Class" because
>> instanceof-ness is defined not just by Class but also by ClassLoader.
>>
>> The IIOProviderContextListener mentioned in that documentation is one
>> strategy to handle the unfortunate way ImageIO caches classes. Another
>> strategy is to put the library into a place where it is accessible to
>> all web applications instead of just one.
>>
>>> Just putting jars in a shared folder did not help.
>>
>> Here is where asking on the Tomcat mailing list *will* be a good idea.
>> Make sure to give your exact Tomcat version and explain where you put
>> the library.
>>
>> Can you post the *entire* stack trace from the failure? It looks like
>> it's incomplete -- it doesn't seem to have a "true root cause". It just
>> says "Could not initialize class" because "Could not initialize class".
>> Somewhere there should be a real root cause like NullPointerException or
>> something that can actually be debugged. Def post that to the Tomcat
>> mailing list as well if you post.
>>
>> -chris
>>
>>
> 


Re: PDFBox JPEG2000 and Tomcat - Revisited

Posted by Joel Hirsh <jo...@gmail.com>.
Thanks for the explanation. I will look towards the tomcat mailing list.

Per your request about the entire stack trace - there is more above the
first call to PDFBox, but the root cause in both cases is indeed
"java.lang.NoClassDefFoundError:
Could not initialize class".
And I have seen that same error with other ClassLoader problems under
Tomcat.

On Wed, Aug 1, 2018 at 1:39 PM, Christopher Schultz <
chris@christopherschultz.net> wrote:

> Joel,
>
> On 8/1/18 3:54 PM, Joel Hirsh wrote:
> > However, your comment that "Tomcat doesn't unload libraries" is not
> > entirely true. There is an explanation of such symptions at
> > https://haraldk.github.io/TwelveMonkeys/, under the section "Deploying
> the
> > plugins in a web app".
>
> Thanks for posting that. Lemmie 'splain.
>
> In a servlet container, web applications (aka "contexts") each have
> their own ClassLoader and if the application is undeployed or
> re-deployed, then that ClassLoader will be freed for GC. If a class
> loaded by that webapp's ClassLoader is still in use, you have a memory
> leak situation knows as a "pinned ClassLoader".
>
> It happens all the time when you use a system-global cache such as
> ImageIO does. This can happen with JDBC DriverManger and a handful of
> other common APIs and it can be a serious problem for servers where
> there are lots of redeployments. You can also start to see errors like
> "ClassCastException: Cannot cast foo.bar.Class to foo.bar.Class" because
> instanceof-ness is defined not just by Class but also by ClassLoader.
>
> The IIOProviderContextListener mentioned in that documentation is one
> strategy to handle the unfortunate way ImageIO caches classes. Another
> strategy is to put the library into a place where it is accessible to
> all web applications instead of just one.
>
> > Just putting jars in a shared folder did not help.
>
> Here is where asking on the Tomcat mailing list *will* be a good idea.
> Make sure to give your exact Tomcat version and explain where you put
> the library.
>
> Can you post the *entire* stack trace from the failure? It looks like
> it's incomplete -- it doesn't seem to have a "true root cause". It just
> says "Could not initialize class" because "Could not initialize class".
> Somewhere there should be a real root cause like NullPointerException or
> something that can actually be debugged. Def post that to the Tomcat
> mailing list as well if you post.
>
> -chris
>
>

Re: PDFBox JPEG2000 and Tomcat - Revisited

Posted by Christopher Schultz <ch...@christopherschultz.net>.
Joel,

On 8/1/18 3:54 PM, Joel Hirsh wrote:
> However, your comment that "Tomcat doesn't unload libraries" is not
> entirely true. There is an explanation of such symptions at
> https://haraldk.github.io/TwelveMonkeys/, under the section "Deploying the
> plugins in a web app".

Thanks for posting that. Lemmie 'splain.

In a servlet container, web applications (aka "contexts") each have
their own ClassLoader and if the application is undeployed or
re-deployed, then that ClassLoader will be freed for GC. If a class
loaded by that webapp's ClassLoader is still in use, you have a memory
leak situation knows as a "pinned ClassLoader".

It happens all the time when you use a system-global cache such as
ImageIO does. This can happen with JDBC DriverManger and a handful of
other common APIs and it can be a serious problem for servers where
there are lots of redeployments. You can also start to see errors like
"ClassCastException: Cannot cast foo.bar.Class to foo.bar.Class" because
instanceof-ness is defined not just by Class but also by ClassLoader.

The IIOProviderContextListener mentioned in that documentation is one
strategy to handle the unfortunate way ImageIO caches classes. Another
strategy is to put the library into a place where it is accessible to
all web applications instead of just one.

> Just putting jars in a shared folder did not help.

Here is where asking on the Tomcat mailing list *will* be a good idea.
Make sure to give your exact Tomcat version and explain where you put
the library.

Can you post the *entire* stack trace from the failure? It looks like
it's incomplete -- it doesn't seem to have a "true root cause". It just
says "Could not initialize class" because "Could not initialize class".
Somewhere there should be a real root cause like NullPointerException or
something that can actually be debugged. Def post that to the Tomcat
mailing list as well if you post.

-chris


Re: PDFBox JPEG2000 and Tomcat - Revisited

Posted by Joel Hirsh <jo...@gmail.com>.
First I was indeed confused about the image formats.  The PDF that caused
the problem does have JBIG2 images according to Acrobat Pre-Flight.
However, Chris' workaround to test for "JPEG2000" corrected the problem in
PDFBox 2.0.7. I have no idea what that is indicative of. Maybe if one
reader was gone, they were all gone?

However, your comment that "Tomcat doesn't unload libraries" is not
entirely true. There is an explanation of such symptions at
https://haraldk.github.io/TwelveMonkeys/, under the section "Deploying the
plugins in a web app".  TwelveMonkeys has a solution for that in the class
"com.twelvemonkeys.servlet.image.IIOProviderContextListener", also
described in that section.  And deploying a listener according to those
instructions solved similar issues with TwelveMonkey Imageio plugins in
PDFBox.  Just putting jars in a shared folder did not help.  There is a
statement there that the class should apply to all ImageIO plugins, but
maybe there is some addition 'glue' that needs to be applied? Or does JBIG
need something similar to TwelveMonkeys?

Thanks

On Wed, Aug 1, 2018 at 11:14 AM, Christopher Schultz <
chris@christopherschultz.net> wrote:

> Joel,
>
> On 8/1/18 1:38 PM, Tilman Hausherr wrote:
> > Am 01.08.2018 um 17:42 schrieb Joel Hirsh:
> >> And what appears to be the same error is back.  Running one JPEG2000
> >> image
> >> is fine, but at some point I get the error
> >>
> >> java.lang.NoClassDefFoundError: Could not initialize class
> >> org.apache.pdfbox.jbig2.JBIG2ImageReader
> >>    at
> >
> >
> > JBIG2ImageReader is for JBIG2 images, not for JPEG2000 images.
> >
> > I suggest you ask the same on the tomcat mailing list, maybe they can
> > help... sadly I don't know more than last time.
>
> ... and before you do, just know that Tomcat doesn't unload libraries...
>
> -chris
>
>

Re: PDFBox JPEG2000 and Tomcat - Revisited

Posted by Christopher Schultz <ch...@christopherschultz.net>.
Joel,

On 8/1/18 1:38 PM, Tilman Hausherr wrote:
> Am 01.08.2018 um 17:42 schrieb Joel Hirsh:
>> And what appears to be the same error is back.  Running one JPEG2000
>> image
>> is fine, but at some point I get the error
>>
>> java.lang.NoClassDefFoundError: Could not initialize class
>> org.apache.pdfbox.jbig2.JBIG2ImageReader
>>    at
> 
> 
> JBIG2ImageReader is for JBIG2 images, not for JPEG2000 images.
> 
> I suggest you ask the same on the tomcat mailing list, maybe they can
> help... sadly I don't know more than last time.

... and before you do, just know that Tomcat doesn't unload libraries...

-chris


Re: PDFBox JPEG2000 and Tomcat - Revisited

Posted by Tilman Hausherr <TH...@t-online.de>.
Am 01.08.2018 um 17:42 schrieb Joel Hirsh:
> And what appears to be the same error is back.  Running one JPEG2000 image
> is fine, but at some point I get the error
>
> java.lang.NoClassDefFoundError: Could not initialize class
> org.apache.pdfbox.jbig2.JBIG2ImageReader
>    at


JBIG2ImageReader is for JBIG2 images, not for JPEG2000 images.

I suggest you ask the same on the tomcat mailing list, maybe they can 
help... sadly I don't know more than last time.

Tilman


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@pdfbox.apache.org
For additional commands, e-mail: users-help@pdfbox.apache.org


Re: PDFBox JPEG2000 and Tomcat - Revisited

Posted by Joel Hirsh <jo...@gmail.com>.
And here is a link to the original post by Chris

 https://lists.apache.org/list.html?users@pdfbox.apache.org:dfr=2017-6-1|dto=2017-8-1:tomcat
<https://lists.apache.org/list.html?users@pdfbox.apache.org:dfr=2017-6-1|dto=2017-8-1:tomcat>

On Wed, Aug 1, 2018 at 8:42 AM, Joel Hirsh <jo...@gmail.com> wrote:

> I was having a problem a month ago with reading JPEG2000 files on tomcat,
> that seemed identical to what is described in a posting to this list by
> Chris Gamache <https://plus.google.com/u/0/101607728077454498498?prsrc=4>
>  <cg...@gmail.com> on Jun 21 2017 with the subject "PDFBox JPEG2000
> and Tomcat".  Basically PDFBox was 'forgetting' about the JPEG2000 library
> at some point, and getting an error when reading a JPEG2000 file.
>
> I reached out to Chris and he was kind enough to offer me his solution,
> which is to check for whether JPEG2000 is loaded before each call to
> PDFBox, and then reload it.  And that seemed to resolve my problem.
>
> I recently upgraded to PDFBox 2.0.11, and removed the library
> levigo-jbig2-imageio-1.6.5.jar as those entry points were now being defined
> in pdfbox-app-2.0.11.jar.
>
> And what appears to be the same error is back.  Running one JPEG2000 image
> is fine, but at some point I get the error
>
> java.lang.NoClassDefFoundError: Could not initialize class
> org.apache.pdfbox.jbig2.JBIG2ImageReader
>   at org.apache.pdfbox.jbig2.JBIG2ImageReaderSpi.createReaderInstance(
> JBIG2ImageReaderSpi.java:117)
>   at javax.imageio.spi.ImageReaderSpi.createReaderInstance(
> ImageReaderSpi.java:320)
>   at javax.imageio.ImageIO$ImageReaderIterator.next(ImageIO.java:529)
>   at javax.imageio.ImageIO$ImageReaderIterator.next(ImageIO.java:513)
>   at org.apache.pdfbox.filter.Filter.findImageReader(Filter.java:155)
>   at org.apache.pdfbox.filter.JBIG2Filter.decode(JBIG2Filter.java:67)
>   at org.apache.pdfbox.cos.COSInputStream.create(COSInputStream.java:77)
>   at org.apache.pdfbox.cos.COSStream.createInputStream(COSStream.java:175)
>   at org.apache.pdfbox.cos.COSStream.createInputStream(COSStream.java:163)
>   at org.apache.pdfbox.pdmodel.common.PDStream.createInputStream(PDStream.
> java:236)
>   at org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject.
> createInputStream(PDImageXObject.java:695)
>   at org.apache.pdfbox.pdmodel.graphics.image.SampledImageReader.
> getStencilImage(SampledImageReader.java:91)
>   at org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject.
> getStencilImage(PDImageXObject.java:483)
>   at org.apache.pdfbox.rendering.PageDrawer.drawImage(
> PageDrawer.java:1029)
>   at org.apache.pdfbox.contentstream.operator.graphics.DrawObject.process(
> DrawObject.java:62)
>   at org.apache.pdfbox.contentstream.PDFStreamEngine.processOperator(
> PDFStreamEngine.java:848)
>   at org.apache.pdfbox.contentstream.PDFStreamEngine.
> processStreamOperators(PDFStreamEngine.java:503)
>   at org.apache.pdfbox.contentstream.PDFStreamEngine.
> processStream(PDFStreamEngine.java:477)
>   at org.apache.pdfbox.contentstream.PDFStreamEngine.
> processPage(PDFStreamEngine.java:150)
>   at org.apache.pdfbox.rendering.PageDrawer.drawPage(PageDrawer.java:246)
>   at org.apache.pdfbox.rendering.PDFRenderer.renderImage(
> PDFRenderer.java:225)
>   at org.apache.pdfbox.rendering.PDFRenderer.renderImageWithDPI(
> PDFRenderer.java:150)
>
> Which is very similar to the error I got with PDFBox 2.0.7 and the levigo
> jar
>
> java.lang.NoClassDefFoundError: Could not initialize class
> com.levigo.jbig2.JBIG2ImageReader
>   at com.levigo.jbig2.JBIG2ImageReaderSpi.createReaderInstance(
> JBIG2ImageReaderSpi.java:118)
>   at javax.imageio.spi.ImageReaderSpi.createReaderInstance(
> ImageReaderSpi.java:320)
>   at javax.imageio.ImageIO$ImageReaderIterator.next(ImageIO.java:529)
>   at javax.imageio.ImageIO$ImageReaderIterator.next(ImageIO.java:513)
>   at org.apache.pdfbox.filter.Filter.findImageReader(Filter.java:120)
>   at org.apache.pdfbox.filter.JBIG2Filter.decode(JBIG2Filter.java:54)
>   at org.apache.pdfbox.cos.COSInputStream.create(COSInputStream.java:69)
>   at org.apache.pdfbox.cos.COSStream.createInputStream(COSStream.java:167)
>   at org.apache.pdfbox.pdmodel.common.PDStream.createInputStream(PDStream.
> java:235)
>   at org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject.
> <init>(PDImageXObject.java:125)
>   at org.apache.pdfbox.pdmodel.graphics.PDXObject.
> createXObject(PDXObject.java:70)
>   at org.apache.pdfbox.pdmodel.PDResources.getXObject(
> PDResources.java:409)
>   at com.moneythumb.convert.i.processOperator(SourceFile:72)
>   at org.apache.pdfbox.contentstream.PDFStreamEngine.
> processStreamOperators(PDFStreamEngine.java:495)
>   at org.apache.pdfbox.contentstream.PDFStreamEngine.
> processStream(PDFStreamEngine.java:469)
>   at org.apache.pdfbox.contentstream.PDFStreamEngine.
> processPage(PDFStreamEngine.java:150)
>
> Also the workaround from Chris was still in place, but did not appear to
> help, although it is not specific to any packaging.  It checks whether the
> reader for format 'JPEG2000' canReadRaster() and if not calls
> IIORegistry.getDefaultInstance.registerApplicationClasspathSpis();.
>
> So my take is that PDFBox inherited whatever problem was there previously
> in the  JBIG2 ImageIO plugin.
>
> And I am surprised that the workaround did not help - I assume the format
> is still known at 'JPEG2000', right?
>
>
>