JDK-4974531 : classes are loaded 512 bytes at a time, slowing down applet start time
  • Type: Bug
  • Component: deploy
  • Sub-Component: plugin
  • Affected Version: 1.4.2
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2004-01-06
  • Updated: 2005-02-02
  • Resolved: 2004-12-10
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other JDK 6
1.4.2_08 b01Fixed 6Fixed
Related Reports
Relates :  
Relates :  
Description
Name: gm110360			Date: 01/06/2004


FULL PRODUCT VERSION :
java version "1.4.1_02"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_02-b06)
Java HotSpot(TM) Client VM (build 1.4.1_02-b06, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]

EXTRA RELEVANT SYSTEM CONFIGURATION :
using Microsoft Internet Explorer 6.0

A DESCRIPTION OF THE PROBLEM :
Starting up a Java application from a DOS command line takes significantly less time (30%) than when the same application is started as an applet, through a browser. Using FileMon trace, I found that in the case of an applet, the classes for the applet as well as the classes from rt.jar are loaded 512 bytes at a time. While in the case of an application, the disk access is done much more efficiently - the whole class is read in one disk access.

We have a large application here and starting it up as an applet takes in the order of 50 seconds, which is unacceptably slow. During that time, rt.jar is accessed in the order of 60,000 times, reading 512 bytes at a time. However, when starting the application from a DOS command line, rt.jar is accessed about 24,000 times and each access loads the full class.



STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. pick any large java program.
2. create a JAR file for it and sign it.
3. embed the applet in a HTML file.
4. specify to use java plugin 1.4.1_02 instead of the browsers JVM by using <OBJECT> tag
5. start up a disk monitoring tool, such as FileMon.
6. using a browser, load the applet - NOTE # disk accesses
7. start the program as an apllication from a DOS command line - NOTE # disk accesses

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Starting the program as an applet should take about the same time as starting it as an application.
ACTUAL -
The applet takes 50 seconds to start, the application takes 30 seconds to start.

REPRODUCIBILITY :
This bug can be reproduced always.
(Incident Review ID: 223584) 
======================================================================

Comments
SUGGESTED FIX For reducing the number of writes: ------- CachedJarLoader.java ------- *** /tmp/sccs.Z_ay0E Tue Oct 5 15:43:29 2004 --- CachedJarLoader.java Thu Sep 16 14:19:08 2004 *************** *** 54,59 **** --- 54,60 ---- // Class to handle loading of jar files from the cache public class CachedJarLoader { + private static int BUF_SIZE = 8192; private URL url; private HttpURLConnection uc = null; private long lastModified = 0; *************** *** 389,400 **** ZipInputStream in = null; ZipOutputStream out = null; try { ! in = new ZipInputStream(new BufferedInputStream(uc.getInputStream())); // Open the output stream out = new ZipOutputStream( new BufferedOutputStream( ! new FileOutputStream(dataFile))); out.setLevel(JarCache.compression); ZipEntry entry = in.getNextEntry(); --- 390,401 ---- ZipInputStream in = null; ZipOutputStream out = null; try { ! in = new ZipInputStream(new BufferedInputStream(uc.getInputStream(), BUF_SIZE)); // Open the output stream out = new ZipOutputStream( new BufferedOutputStream( ! new FileOutputStream(dataFile), BUF_SIZE)); out.setLevel(JarCache.compression); ZipEntry entry = in.getNextEntry(); *************** *** 515,521 **** // Open the output stream out = new ObjectOutputStream( new BufferedOutputStream( ! new FileOutputStream(raf.getFD()))); manifest = jar.getManifest(); //If no manifest, no need to worry about authentication --- 516,522 ---- // Open the output stream out = new ObjectOutputStream( new BufferedOutputStream( ! new FileOutputStream(raf.getFD()), BUF_SIZE)); manifest = jar.getManifest(); //If no manifest, no need to worry about authentication *************** *** 683,689 **** // Create an input stream in = new ObjectInputStream( new BufferedInputStream( ! new FileInputStream(raf.getFD()))); // Read the manifest int manifestLength = in.readInt(); --- 684,690 ---- // Create an input stream in = new ObjectInputStream( new BufferedInputStream( ! new FileInputStream(raf.getFD()), BUF_SIZE)); // Read the manifest int manifestLength = in.readInt(); --- For reducing the number of reads: ------- ZipFile.java ------- *** /tmp/sccs.rDaq1E Tue Oct 5 15:50:53 2004 --- ZipFile.java Thu Sep 30 17:35:27 2004 *************** *** 207,213 **** case STORED: return zfin; case DEFLATED: ! return new InflaterInputStream(zfin, getInflater()) { private boolean isClosed = false; public void close() throws IOException { --- 207,213 ---- case STORED: return zfin; case DEFLATED: ! return new InflaterInputStream(zfin, getInflater(), 8192) { private boolean isClosed = false; public void close() throws IOException { ###@###.### 10/5/04 22:54 GMT
05-10-2004

CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: 1.4.2_07
26-08-2004

EVALUATION Stanley was working with networking team on this issue. Reassign to Stanley. ###@###.### 2004-01-07 The problem is in sun/plugin/PluginURLJarFileCallBack.java. When retrieve() is called, the JAR file would be saved into the local temp file through BufferedOutputStream. However, the default buffer size of BufferedOuputStream is 512KB instead of the more efficient 8192KB, thus it degrade the performance. This problem has been fixed in Tiger already, but it should be backported to 1.4.2_0x. Reassign to CTE. ###@###.### 2004-02-10 For the applet case, there're actually 2 issues - the number of writes when cacheing the jar file and the number of reads when reading the jar file. The reading of jar file 512 bytes at a time is not limited to applet. Same problem can be observed when running a test applet such as SwingSet2 with appletviewer or as a standalone application (java -jar). The number of writes problem can be fixed in the java plugin CachedJarLoader by increasing the buffer size when instantiating io streams such as FileOutputStream. The number of reads problem can be fixed in the java/util/zip/ZipFile by increasing the buffer size when instantiating InflaterInputStream. However, initial assessment by TL team is that the change will cause performance degradation for small applications and shouldn't be made in an update release. The number of reads problem still exists in Tiger. The increase in the default buffer size in BufferedInputStream and BufferedOutputStream in Tiger has no effect on the number of reads. The number of writes problem seems to have been fixed in Tiger. ###@###.### 10/5/04 22:54 GMT
05-10-0004