java jre 7u45 breaks classloader.getResources()?

Chris Holt picture Chris Holt · Oct 16, 2013 · Viewed 7.2k times · Source

I have code to iterate over the results of classLoader.getResources("META-INF/MANIFEST.MF") to return the list of jars on the class path. This worked fine from 1.6.0_18 all the way to 1.7.0_40. Now 1.7.0_45 breaks this by showing a security warning popup about mixed signed/unsigned code.

Small self contained testcase to demonstrate problem:

package testcase;
import java.io.*;
import java.net.*;
import java.util.Enumeration;
import java.util.logging.*;
public class TestCase {
    public static void main(String[] args) {
        getAllJarUrls();
    }

    public static void getAllJarUrls() {
        try {
            final Enumeration<URL> mfUrls = Thread.currentThread().getContextClassLoader().getResources("META-INF/MANIFEST.MF");
            while (mfUrls.hasMoreElements()) {
                URL jarUrl = mfUrls.nextElement();
                if (!jarUrl.getProtocol().equals("jar")) {
                    continue;
                }
                try {
                    System.out.println(jarUrl.toURI());
                } catch (URISyntaxException ex) {
                    Logger.getLogger("testcase").log(Level.SEVERE, null, ex);
                }
            }
        } catch (IOException e) {
            Logger.getLogger("testcase").log(Level.SEVERE, null, e);
        }
    }
}

Launch this with a jnlp (jar signed with a valid certificate) as:

<?xml version="1.0" encoding="UTF-8"?>
<jnlp spec="1.0+" codebase="http://localhost/test" href="test.jnlp">
    <information>
        <title>test</title>
        <vendor>test</vendor>
      </information>
    <security><all-permissions/></security>
    <resources>
        <jar href="testcase.jar" main="true" download="eager"/>
    </resources>
    <application-desc main-class="testcase.TestCase"/>
</jnlp>

When run, have the console visible, and hit '5' for verbose output. then click 'block' on the security prompt to see the exception. Clicking allow will let the code run normally, but this is not an acceptable user experience. especially since our application has to be able to start without user input.

Output under 1.7.0_45 is as follows:

CacheEntry[http://localhost/test/testcase.jar]: updateAvailable=true,lastModified=Tue Oct 15 21:09:21 CDT 2013,length=6314
jar:file:/C:/jre32/1.7.0_45/lib/javaws.jar!/META-INF/MANIFEST.MF
jar:file:/C:/jre32/1.7.0_45/lib/deploy.jar!/META-INF/MANIFEST.MF
jar:file:/C:/jre32/1.7.0_45/lib/plugin.jar!/META-INF/MANIFEST.MF
jar:file:/C:/jre32/1.7.0_45/lib/deploy.jar!/META-INF/MANIFEST.MF
Trace level set to 5: all ... completed.Trace level set to 5: all ... completed.
security: resource name "META-INF/MANIFEST.MF" in http://localhost/test/testcase.jar : java.lang.SecurityException: trusted loader attempted to load sandboxed resource from http://localhost/test/testcase.jar

The testcase.jar is signed. It even has all the new manifest attributes included: Application-Name: testcase Permissions: all-permissions Codebase: *

A diff of the decompiled CPCallBackHandler from deploy.jar from 7u40 to 7u45 shows significant changes. It looks like the changes for LiveConnect have borked the existing functionality. And no, there's no LiveConnect involved here.

Has anyone else run into this? Suggestions for a workaround? File a bug?

(note: also posted on the OTN java forums, but I'm hoping for a faster answer here :).

Thanks, Chris

Answer

Chris Holt picture Chris Holt · Oct 16, 2013

Add this to the manifest of the jar:

Trusted-Library: true

Documented here.