JDK-8178799 : Under Java 9 Java Web Start consumes the only URLStreamHandlerFactory slot
  • Type: Bug
  • Component: deploy
  • Sub-Component: webstart
  • Affected Version: 9
  • Priority: P2
  • Status: Resolved
  • Resolution: Fixed
  • OS: linux_ubuntu
  • CPU: x86_64
  • Submitted: 2017-04-11
  • Updated: 2018-12-02
  • Resolved: 2017-05-11
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.
JDK 10
10 b23Fixed
Related Reports
Relates :  
Relates :  
Sub Tasks
JDK-8181649 :  
Description
FULL PRODUCT VERSION :
java version "9-ea"
Java(TM) SE Runtime Environment (build 9-ea+163)
Java HotSpot(TM) 64-Bit Server VM (build 9-ea+163, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
Linux ubuntu1204-XXXXXXX 3.5.0-45-generic #68~precise1-Ubuntu SMP Wed Dec 4 16:18:46 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux


EXTRA RELEVANT SYSTEM CONFIGURATION :
Not related to OS.

A DESCRIPTION OF THE PROBLEM :
URL.setURLStreamHandlerFactory() permits only one call to set a factory. When a second call is made an exception is thrown with the message "factory already defined".

Starting with Java 9, in Java Web Start (JNLP), this call is made before the application starts, prohibiting applications from using the facility. This does not happen in Java 8, nor does it happen when the application is launched directly with java on the command line.

I have an application that runs fine in Java 8, that supplies its own URLStreamHandlerFactory. This application is blocked from working in Java 1.9 from a JNLP launch.



REGRESSION.  Last worked in version 8u121

ADDITIONAL REGRESSION INFORMATION: 
It works in all Java 8 versions.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Compile supplied source .
2. put it in a jar (test.jar), and sign it.
3. compose a JNLP like this (with appropriate substitution for the path):
<?xml version="1.0" encoding="UTF-8"?>
<jnlp spec="1.5+" codebase="file:///[local director without leading slash here]" href="test.jnlp" version="1.0" >
    <information>
        <title>Set a URLStreamHandler</title>
        <vendor>Test</vendor>
        <offline-allowed/>
    </information>
    <security>
        <all-permissions />
    </security>
    <resources>
        <java version="1.8+"/>
        <jar href="test.jar" main="true" download="lazy" />
    </resources>
    <application-desc main-class="com.test.URLFactoryMain"/>
</jnlp>
4. Change your security settings in the java control panel to include the uri used in the code base and href.
5. Run with Java 8 "java -cp . com.test.URLFactoryMain" - success
6. Run with Java 8, "javaws test.jnlp" - success
7. Run with Java 9 "java -cp . com.test.URLFactoryMain" - success
8. Run with Java 9, "javaws test.jnlp" - failure



EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
When run with either Java 8 or Java 9, command line or with Java Web Start, it should run no exceptions.
ACTUAL -
When run with Java 9, using Java Web Start, it fires an exception with message "factory already defined".

ERROR MESSAGES/STACK TRACES THAT OCCUR :
#### Java Web Start Error:
#### java.lang.Error: factory already defined

java.lang.Error: factory already defined
	at java.base/java.net.URL.setURLStreamHandlerFactory(Unknown Source)

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
package com.test;

import java.net.URL;
import java.net.URLStreamHandler;
import java.net.URLStreamHandlerFactory;

public class UrlFactoryMain {
	private static class TestURLHandlerFactory implements URLStreamHandlerFactory {
		@Override
		public URLStreamHandler createURLStreamHandler(String protocol) {
			return null;
		}
	}
	public static void main(String[] args) {
		URL.setURLStreamHandlerFactory(new TestURLHandlerFactory());
	}
}
---------- END SOURCE ----------


Comments
When will this fix in jdk10 be back ported to jdk9? One of our customers wants that this bug is also fixed in jdk9.
08-06-2017

adding export statements in jdk.deploy's module-info resolves this problem - and all regression tests now pass. resubmitting Crucible review at: https://java.se.oracle.com/code/cru/CR-JDK10CLIENT-32
05-05-2017

The problem is caused by URL class (after reading system property) trying to create the handler classes, and gets: java.lang.IllegalAccessException: class java.net.URL (in module java.base) cannot access class com.sun.deploy.net.protocol.https.Handler (in module jdk.deploy) because module jdk.deploy does not export com.sun.deploy.net.protocol.https to module java.base need additional export statement(s) in jdk.deploy module-info.java
04-05-2017

this change causes regressions in regression/plugin/LiveConnectSupportClientTest, LaunchJVMAppletMessageTest, and CachedJarURLConnectionTest - so clearly is not working as I expected - investigating
02-05-2017

Crucible review: https://java.se.oracle.com/code/cru/CR-JDK10CLIENT-32
01-05-2017

initial testing shows removing call to URL.setURLStreamHandlerFactory() and replacing with call to set system property "java.protocol.handler.pkgs" appropriately seems to work.
28-04-2017

In JDK8 and before, we used the System property "java.protocol.handler.pkgs" to point to the packages that contain the needed protocol handlers (in javaws that was "com.sun.javaws.net.protocol|com.sun.deploy.net.protocol", in plugin that was "sun.plugin.net.protocol|com.sun.deploy.net.protocol") The system property "java.protocol.handler.pkgs" was dropped in JDK9 (as part of JDK-8064924) in JDK9, as part of JDK-8073799, we switched to using URL.setURLStreamHandlerFactory(). Later in JDK9, support for this SystemProperty was restored with JDK-8075139, so it might be possible to switch back to it's usage.
28-04-2017

This seems a regression in 9 as the test run fine with 8u121 b13. In Java 9, the call to URL.setURLStreamHandlerFactory() is made prior to start of application thus restricting them to use the facility. Subsequent call throws and exception with the message "factory already defined". 9 ea b164 run: ===================== java.lang.Error: factory already defined at java.base/java.net.URL.setURLStreamHandlerFactory(URL.java:1184) at URLFactoryMain.main(URLFactoryMain.java:13) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ======================== To reproduce run the jnlp provided in subsequent comment. Note: Provided test case had error with reference to class name. Recompiled the test case with correction and run to verify the issue. Result: ============ 8u121 b13: OK 9 ea b164: FAIL
14-04-2017