I have an application that I'm deploying with Java Web Start. When I was doing unit testing, I noticed a slight problem: whenever my application is run with Java Web Start, a particular operation takes a long time to execute. When run locally, however, it is quite fast.
The particular operation I'm talking about is reading in a large (5k row) Excel file to parse it. This is the line of code:
Workbook wb = WorkbookFactory.create(new FileInputStream(new File(inputFile.getText())));
To figure out the problem, I added a way to record the time:
long time1 = System.currentTimeMillis();
Workbook wb = WorkbookFactory.create(new FileInputStream(new File(inputFile.getText())));
long time2 = System.currentTimeMillis();
long diff = time2 - time1;
double seconds = (double)diff / (double)1000;
DecimalFormat df = new DecimalFormat("#,##0.00");
System.out.println("Elapsed Time: " + df.format(seconds) + " seconds.");
And this is the ouput:
(local)
Elapsed Time: 4.83 seconds.
(Java Web Start)
Elapsed Time: 35.52 seconds.
BUT THEN, an immediate subsequent run (on Java Web Start) yields this:
Elapsed Time: 1.61 seconds.
My suspicion is that this has to do with the POI library (in particular, the size of the library required to read POI, more specifically, the 13 MB ooxml-schemas-1.0.jar
library file). So, my question is: assuming it is the library size, is there any way to prevent this? I have library caching turned on through the control panel, so why does it seem to need to be caching the library? Once it is loaded, it's fast. But it takes forever the first time.
Here's an image of the control panel showing that I am allowing it to store the libraries:
Has anyone seen this kind of behavior before? No SSCCE because... well, how do you post an SSCCE with a Java Web Start question?
In light of any profiling results, you should critically review the <resources/>
attributes specified in the <j2se/>
element of your .jnlp
and compare them to those in your development environment. In particular, look at those affecting performance, such as heap size and VM type:
<resources>
<j2se
version="1.6+"
initial-heap-size="128m"
max-heap-size="256m"
java-vm-args="-server"/>
…
</resources>
I can see two things that won't be helping. Not sure if they'll account for the full difference, but at least some...
First up, the line
WorkbookFactory.create(new FileInputStream(new File(inputFile.getText())));
You had a perfectly good file object, now you're wasting a load of time and resources buffering it all into memory. As quite clearly explained in the POI documentation, if you have a File, use it directly! You'll save time and memory switching that (as shown in the docs) to:
WorkbookFactory.create(new File(inputFile.getText()));
.
Secondly, from the POI components page:
poi-ooxml requires poi-ooxml-schemas. This is a substantially smaller version of the ooxml-schemas jar ... The larger ooxml-schemas jar is normally only required for development
So, unless you have some very special needs, switch out the complete ooxml-schemas
jar for the much much smaller poi-ooxml-schemas
jar, which will cover you for all the common use cases. That'll make your loading much quicker too.
If you in your jnlp by mistake set the download attribute to lazy, you should state that you want to download this library eagerly
<resources>
<jar download="eager" href="uploads/lib/guice-multibindings-3.0.jar"/>
</resources>
Which means they will be cached before application launches
By default, jar and nativelib resources will be downloaded eagerly,
i.e., they are downloaded and available locally to the JVM running the
application before the application is launched. The jar and nativelib
elements also allow a resource to be specified as lazy. This means
the resource does not have to be downloaded onto the client system
before the application is launched.
from http://docs.oracle.com/javase/7/docs/technotes/guides/javaws/developersguide/syntax.html
I had a similar issue but with loading a .docx document (XWPFDocument) from a file. While doing it locally, it took under 1 second to load the file; however, doing it via Java Web Start it took around 35 seconds for me, and even half an hour for my colleague. Here's how I got it solved, hopefully it might solve this issue as well.
The culprit was the Apache XMLBeans library, or rather the incorrect way it has been used in Apache POI. The XMLBeans library included with the Apache POI release is version 2.3.0 and the jar file is xmlbeans-2.3.0.jar. If you include this in your classpath while launching a program locally, it'll work just fine. However, if you include it in your .jnlp file as a resource and launch your program with Web Start, it'll work really slowly as you explained. If you open the Java Console and set trace level to 5, you'll see that when you load the .docx file, the program will look for a resource xbean.jar even though you probably don't even have this in your .jnlp file. This will cause the program to look for the resource until it times out, and probably will try again many times, causing the slow loading time.
There's a bug report about this in the POI Bugzilla from 2011 (Bug 51660).
I solved this by downloading XMLBeans version 2.5.0 and instead of including the xmlbeans-2.3.0.jar I included the xbean.jar and jsr173_1.0_api.jar in the classpath and as resources in the .jnlp file.