This problem is hindering Oracle's ability to run java applications in OC4J.
Here is the stack for the error:
Exception in thread "main" java.lang.RuntimeException: null certificates for com
/sun/crypto/provider/DESKeyFactory.class
at CertificateTest.checkEntry(CertificateTest.java:137)
at CertificateTest.main(CertificateTest.java:81)
Here is the source code to re-create the problem. An additional text file with class file name entries(testscript.txt) is required to complete the test case. I've incorporated the content at the end of this text.
/*
* Test Case: JarEntry.getCertificates() returns null when memory is strained.
*/
import java.io.*;
import java.util.*;
import java.util.jar.*;
import java.security.cert.Certificate;
// This test should be run more than once, as it sometimes succeeds and
// sometimes fails. The probability of success appears related to the
// length of the testscript.txt input file. In general, cloning lines
// in the middle of testscript.txt appears to increase the probability
// of failure.
public class CertificateTest
{
// Simulate heavy memory usage; the number of bytes to eat in
// order to reproduce the failure depends on the length of the input script.
// Adding a few thousand lines in the middle of the script will reduce
// the required EAT_BYTES size by several orders of magnitude.
static final boolean EAT_MEMORY = true;
static final int EAT_BYTES = 700000;
static final String INPUT_SCRIPT_FILE = "testscript.txt";
private static byte[] buffer;
public static void main(String[] args)
throws IOException
{
FileInputStream in = new FileInputStream(INPUT_SCRIPT_FILE);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
ArrayList memoryEater = new ArrayList();
TreeMap tmJarFiles = new TreeMap();
int openJarCount = 0;
int getEntryCount = 0;
int nLine = 0;
for (;;)
{
String sLine = br.readLine();
++nLine;
// System.out.println("Line " + nLine);
if (sLine == null)
break;
if (sLine.startsWith("open "))
{
String sTarget = sLine.substring(5);
System.out.println("open [" + sTarget + "]");
if (!tmJarFiles.containsKey(sTarget))
{
++openJarCount;
JarFile jf = new JarFile(sTarget);
tmJarFiles.put(sTarget, jf);
}
}
else if (sLine.startsWith("getJarEntry "))
{
getEntryCount++;
if (EAT_MEMORY)
memoryEater.add(new byte[EAT_BYTES]);
int nInPos = sLine.indexOf(" in ");
String entryName = sLine.substring(12, nInPos);
String fileName = sLine.substring(nInPos + 4);
// System.out.println("getJarEntry [" + entryName + "] from [" + fileName + "]");
JarFile jf = (JarFile) tmJarFiles.get(fileName);
if (jf == null)
throw new RuntimeException("jar file not in list: " + fileName);
JarEntry entry = jf.getJarEntry(entryName);
if (entry == null)
throw new RuntimeException("didn't find entry " + entryName + " in " + jf);
checkEntry(jf, entry, entryName);
}
}
br.close();
// successful outcome
System.out.println("\n Test succeeded");
System.out.println(" " + getEntryCount + " getJarEntry calls");
System.out.println(" " + openJarCount + " open jars");
}
static void checkEntry(JarFile jar, JarEntry entry, String entryName)
throws IOException
{
Certificate[] certs = null;
int entrySize = (int) entry.getSize();
InputStream in = null;
try
{
in = jar.getInputStream(entry);
if (buffer == null || entrySize > buffer.length)
buffer = new byte[entrySize];
int bytesUsed = 0;
for (int remaining = entrySize; remaining > 0; )
{
int readSize = in.read(buffer, bytesUsed, remaining);
if (readSize == -1)
throw new IOException("Unexpected EOF");
remaining -= readSize;
bytesUsed += readSize;
}
certs = entry.getCertificates();
}
finally
{
if (in != null)
in.close();
}
if (certs == null)
{
// With 'memory eating' disabled we find 2 certificates for
// this entry. With 'memory eating' enabled, we usually get a null.
// Reducing the length of the input script by chopping lines out
// of the middle appears to increase the probability of correctly
// retrieving the certificates.
if (entryName.equals("com/sun/crypto/provider/DESKeyFactory.class"))
{
System.out.println("\n** FAILED ***\n");
throw new RuntimeException("null certificates for " + entry);
}
}
}
}
open sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE_al.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE_al.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE_al.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE_al.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE_al.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE_al.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE_al.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE_al.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE_al.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE_al.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE_al.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE_al.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE_al.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE_al.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE_al.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE_al.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE_al.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE_al.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE_al.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE_al.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/SunJCE.class in sunjce_provider.jar
getJarEntry com/sun/crypto/provider/DESKeyFactory.class in sunjce_provider.jar
Release Regression From : 5.0u3
The above release value was the last known release where this
bug was known to work. Since then there has been a regression.
###@###.### 2005-07-20 17:38:29 GMT