JDK-6460510 : Applet throws OutOfMemory/ClassNotFound exception with cache enabled
  • Type: Bug
  • Component: deploy
  • Sub-Component: plugin
  • Affected Version: 6
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2006-08-16
  • Updated: 2010-04-04
  • Resolved: 2006-09-28
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.
6 b97Fixed
Applet throws ClassNotFound exception with cache enabled

builds reproducible - b38 onwards
The bug is not reproducible on b37

OS tested - Win XP Pro, Win XP Home
browsers tested - IE6.0, MZ 1.7.x

Steps to reproduce

1) Install jre1.6.0 b37 or later

2) Delete the folder "java" 
C:\Documents and Settings\{User}\Application data\Sun

3) Open Java Control Panel, and enable "Show java console" and "Show Applet Lifecycle Exceptions"

4) Make sure the cache is enabled
General -> Settings ->Temporary Files Settings
"Keep temporary files on my computer" should be checked

4) Open the browser and launch the following applet

5) Only three of the six frames are loaded and ClassNotFound exceptions are thrown in the java console. Please see the attachment for the exceptions thrown

6) Now open the Java Control Panel and disable cache
General -> Settings ->Temporary Files Settings
"Keep temporary files on my computer" should be unchecked

7) Load the above applet again, and the applet loads fine and no exceptions are thrown.

expected behavior - no exceptions should be thrown with cache enabled.

EVALUATION The cause of the OutOfMemory exception is due to the way we use the ResponseCache. We create a ByteArrayOutputStream and use a byte[] to hold the jar contents in memory, and after everything is downloaded in memory, we then write it out to cache. This will cause OutOfMemory exception easily, since all the jar contents is stored in memory first, before we write it out to file system. We should instead use a FileOutputStream for the CacheRespose, so we will write out the file as the download proceeds, instead of storing everything into the memory first.

SUGGESTED FIX http://web-east.east/deployment/www/webrevs/ngthomas/6460510/webrev/

WORK AROUND set -Xmx192m, the applet will run

EVALUATION the problem is for 6.0 plugin, we depend on the java.net.ResponseCache for resource downloading. i created a same standalone java testcase, with ResponseCache, which downloads the 2 jar files (40mb and 20mb) as in the plugin applet test, and it will run into outOfMemory exception too. Need to contact the networking team and see if we are using the ResponseCache for downloading correctly. Standalone testcase source code below: import java.net.*; import java.io.*; import java.util.*; import javax.swing.*; class test extends ResponseCache { private static int BUF_SIZE = 8192; public CacheResponse get(URI uri, String rqstMethod, Map<String,List<String>> rqstHeaders) throws IOException { return null; } public CacheRequest put(URI uri, URLConnection conn) throws IOException { URL url = uri.toURL(); return new CacheRequest(url, conn); } class ByteArrayOutputStream extends java.io.ByteArrayOutputStream { private URL _url; private URLConnection _conn; ByteArrayOutputStream(URL url, URLConnection conn) { _url = url; _conn = conn; } public void close() throws IOException { ByteArrayInputStream bais = new ByteArrayInputStream(toByteArray()); byte[] buf = new byte[BUF_SIZE]; int read = 0; File nestedJar = File.createTempFile("jar_cache", null); BufferedInputStream nestedIn = new BufferedInputStream(bais); BufferedOutputStream nestedOut = new BufferedOutputStream(new FileOutputStream(nestedJar)); read = 0; while ((read = nestedIn.read(buf)) != -1) nestedOut.write(buf, 0, read); nestedOut.close(); nestedOut = null; super.close(); } } class CacheRequest extends java.net.CacheRequest { private URL _url; private URLConnection _conn; private boolean _downloading = false; CacheRequest(URL url, URLConnection conn) { _url = url; _conn = conn; } public void abort() { } public OutputStream getBody() throws IOException { return new ByteArrayOutputStream(_url, _conn); } } public static void main(String[] args) { //JFrame jf = new JFrame("dummy"); //jf.show(); test t = new test(); ResponseCache.setDefault(t); try { System.out.println("download test22.jar"); downloadURL(new URL("http://sqeweb.sfbay.sun.com/deployment1/deployment_tiger_exec_ws/deployment/src/plugin/phonehome/classes/Test22.jar")); System.out.println("download test31.jar"); downloadURL(new URL("http://sqeweb.sfbay.sun.com/deployment1/deployment_tiger_exec_ws/deployment/src/plugin/phonehome/classes/Test31.jar")); } catch (Exception e) { e.printStackTrace(); } } public static void downloadURL(URL url) throws IOException { InputStream is = null; URLConnection conn = url.openConnection(); try { // this calls into CacheHandler.get byte[] buf = new byte[BUF_SIZE]; is = new BufferedInputStream(conn.getInputStream()); while (is.read(buf) != -1) { } } finally { if (is != null) { // this calls into CacheHandler.put is.close(); } } } }

EVALUATION we run into OutOfMemory exception when this occurs: java.lang.OutOfMemoryError: Java heap space at java.util.Arrays.copyOf(Unknown Source) at java.io.ByteArrayOutputStream.write(Unknown Source) at sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.read(Unknown Source) at java.io.BufferedInputStream.read1(Unknown Source) at java.io.BufferedInputStream.read(Unknown Source) at java.io.FilterInputStream.read(Unknown Source) at sun.plugin.PluginURLJarFileCallBack$1.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at sun.plugin.PluginURLJarFileCallBack.retrieve(Unknown Source) at sun.net.www.protocol.jar.URLJarFile.retrieve(Unknown Source) at sun.net.www.protocol.jar.URLJarFile.getJarFile(Unknown Source) at sun.net.www.protocol.jar.JarFileFactory.get(Unknown Source) at sun.net.www.protocol.jar.JarURLConnection.connect(Unknown Source) at sun.plugin.net.protocol.jar.CachedJarURLConnection.connect(Unknown Source) at sun.plugin.net.protocol.jar.CachedJarURLConnection.getJarFileInternal(Unknown Source) at sun.plugin.net.protocol.jar.CachedJarURLConnection.getJarFile(Unknown Source) at sun.misc.URLClassPath$JarLoader.getJarFile(Unknown Source) at sun.misc.URLClassPath$JarLoader.access$600(Unknown Source) at sun.misc.URLClassPath$JarLoader$1.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at sun.misc.URLClassPath$JarLoader.ensureOpen(Unknown Source) at sun.misc.URLClassPath$JarLoader.<init>(Unknown Source) at sun.misc.URLClassPath$3.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at sun.misc.URLClassPath.getLoader(Unknown Source) at sun.misc.URLClassPath.getLoader(Unknown Source) at sun.misc.URLClassPath.getResource(Unknown Source) at java.net.URLClassLoader$1.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(Unknown Source) at sun.applet.AppletClassLoader.findClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) basic: Exception: java.lang.OutOfMemoryError: Java heap space Need to investigate the cause of it.