Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 4648098
Votes 37
Synopsis URL.getURLStreamHandler should use Thread.getContextClassLoader() classloader
Category java:classes_net
Reported Against 1.4 , 1.3.1 , 1.4.1
Release Fixed
State 6-Fix Understood, request for enhancement
Priority: 4-Low
Related Bugs 4768774 , 4768311 , 4826413
Submit Date 06-MAR-2002
Description




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

FULL OPERATING SYSTEM VERSION : Debian 3.0 (Sid)


ADDITIONAL OPERATING SYSTEMS : All platforms (it's a
library issue)



A DESCRIPTION OF THE PROBLEM :
URL.getURLStreamHandler tries to load Handlers according
to the java.protocol.handler.pkgs system property. It
does this by trying to load the Handler class
via the Class.forName() and SystemClassLoader. This does
not work when a Servlet tries to add a resource handler
that is included in the WEB-INF part of a .war. This is
because these classes are loaded neither by the System
classloader, nor the loader that loaded java.lang.URL
(which presumably is also the systemclassloader). In
Java2 a new ClassLoader reference mechanism was added:
the Thread context classloader
(Thread.getContextClassLoader()). The URL class should
also try this loader as otherwise the resource-handler
should be included on the system classpath with is not
always possible.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Create a servlet that includes a custom resource
handler in it's WEB-INF/lib directory.
2. Set the -Djava.protocol.handler.pkgs property to the
package of the resource handler.
3. Start this servlet under Tomcat 4.0.2
4. See the Handler NOT get loaded

EXPECTED VERSUS ACTUAL BEHAVIOR :
I expected the URL class to honour the setting of the
java.protocol.handler.pkgs property, instead it only tried
to load the Handler from the system-provided classes.

This bug can be reproduced always.

---------- BEGIN SOURCE ----------
A testcase would be too long for this box. E-mail me for more information.
---------- END SOURCE ----------

CUSTOMER WORKAROUND :
Include the resource handler on the system-classpath
(NOTE: this is a temporary solution, as an ISP/ASP is
unlikely to allow this on a shared hosting system!)
(Review ID: 139951) 
======================================================================




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


FULL OPERATING SYSTEM VERSION :

 customer  Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
URL.getURLStreamHandler() does not consult the
Thread.currentThread().getContextClassLoader() when
looking for handler classes with package prefix names in
java.protocol.handler.pkgs

Since, URL.getURLStreamHandler() calls Class.forName
(String), which will:

  return forName0(className, true,
ClassLoader.getCallerClassLoader());

If I understand this correctly, then the return of
ClassLoader.getCallerClassLoader() will be the system or
rather bootsrap CL, since that is what has loaded URL
(URL.class.getClassLoader() returns null).

So any attempt to Class.forName() done in URL will only
succeed in load classed from the bootstrap cl.

Back in URL, after failing to Class.forName() it will try
the system cl and then give up.

Looks like unless there are class on the system or
bootstrap cl then Class.forName() just won't work.

URL should be fixed to load from TCL which should fix this
problem.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
  Too complicated to list actual steps.  Setup a cl which
loads the bulk of your classes which includes the protcol
handler.  Set java.protocol.handler.pkgs with the correct
prefix.

Create a new instance of a class using the cl you made,
have that class create a URL with a custom protocol.

It will never work.

EXPECTED VERSUS ACTUAL BEHAVIOR :
URL.getURLStreamHandler() should do this:

try {
   ClassLoader cl = Thread.currentThread
().getContextClassLoader();
   if (cl != null) {
      cls = cl.loadClass(clsName);
   }
   if (cls == null) {
      cls = Class.forName(clsName);
   }
} 
catch (ClassNotFoundException e)
   ClassLoader cl = ClassLoader.getSystemClassLoader();
   if (cl != null) {
      cls = cl.loadClass(clsName);
   }
}

This bug can be reproduced always.

---------- BEGIN SOURCE ----------
too complicated.
---------- END SOURCE ----------

CUSTOMER WORKAROUND :
Use a URLStreamHandlerFactory which will load from TCL.
(Review ID: 143413)
======================================================================
Work Around
N/A
Evaluation
This definitely reduces the usefulness of user defined handlers.
Fix also looks simple, so should do for mantis.

  xxxxx@xxxxx   2002-08-21

We have to back this out. There is insufficient time
to verify all of the security implications of this change.
Will reconsider for tiger.

  xxxxx@xxxxx   2002-10-24

See also 4768774. Investigate whether callers class loader
should be used instead of system class loader.

  xxxxx@xxxxx   2002-10-30
Comments
  
  Include a link with my name & email   

Submitted On 16-MAR-2002
pleursoft
The given workaround will not work in a servlet container 
such as tomcat which already sets the 
URLStreamHandlerFactory on java.net.URL. This handler can 
only be registered once in the VM (which is pretty silly btw.).


Submitted On 10-APR-2002
jcaron
I suspect that this is also preventing applications that 
use WebStart from using java.protocol.handler.pkgs property 
to set protocol handlers. (I will file this as a seperate 
report).

IMHO, this is a bug, not an RFE.


Submitted On 22-APR-2002
marc_carrion
I also think this rfe should be an error.


Submitted On 22-APR-2002
marc_carrion
Sorry, I mean, I think this rfe should be a bug, too


Submitted On 28-JUN-2002
sisqbatas
In my opinion, this should be a bug too, since I think it
wasn't expected to work only with handlers loaded by the
system classloader.

BTW, is there any plan to fix it? It was reported 3 months
ago and it's not fixed neither in 1.4.01 nor in 1.4.1 (the
solution doesn't seems so difficult) ...


Submitted On 26-JUL-2002
asmodeus
I can confirm that this issue does affect WebStart.
It prevents my project from loading XSLT fragments with 
a custom resource: URL


Submitted On 24-DEC-2002
tangjia
Although webstart does not set its own 
URLStreamHandlerFactory, custom URLStreamHandlerFactory 
can be set to load custom resources. However, 
JNLPClassLoader has the same problem above, 
See also 4768774. So even if I use my own 
URLStreamHandlerFactory, in my situation, it does't work. 
This bug should be fixed ASAP!!!!!!


Submitted On 24-DEC-2002
tangjia
d


Submitted On 24-DEC-2002
tangjia
sorry, this should be a bug. It does affect webstart, which in 
my project, leads to ClassCircularityError when I am trying to 
load custom resources from tomcat.


Submitted On 22-NOV-2004
NiclasH
This is very serious, and NOT A BUG. So please change this ticket to a Bug instead of RFE since it won


Submitted On 22-NOV-2004
NiclasH
This is very serious, and NOT A BUG. So please change this ticket to a Bug instead of RFE since it will not get any attention otherwise.
It was not fixed for Tiger. There is NO suitable workaround. There are at least two reasonable fixes;
a. Change so that the real callers classloader, and not java.net.URL is used.
b. Use Context classloader.
Somehow, I think the security implications is a bad excuse, and I would really like to see the summary of the security concerns involved, as I think there are no such evaluation done.


Submitted On 11-DEC-2006
superuser33
How about a reasonable API for this instead, maybe for JDK7?

All we really need is 2 static methods:
setURLStreamHandler(String protocol, URLStreamHandler handler);
getURLStreamHandler(String protocol);

Old package-based method can be kept for 100% backwards compatibility.

Sound reasonable?


Submitted On 16-OCT-2007
URL.setURLStreamHandlerFactory() may help

http://java.sun.com/j2se/1.4.2/docs/api/java/net/URL.html#setURLStreamHandlerFactory(java.net.URLStreamHandlerFactory)


Submitted On 26-FEB-2008
This bug is still present in JDK 6 with Tomcat 5.5 and renders java.net.URL useless when passing URL specs containing 3rd party schemes. 

This ticket should receive more attention IMHO.

I have started a discussion on this on the Tomcat mailing list:
http://thread.gmane.org/gmane.comp.jakarta.tomcat.user/162598


Submitted On 26-FEB-2008
In addition to my last comment, here is my take on this issue:

My proposal is to move the code performing checks for existing URL handlers from the constructor to the time when a client actually tries to open a connection from that URL.

I also consider it bad design that java.net.URL throws MalformedUrlException on construction when merely a handler is missing for the given protocol but the URL spec itself is wellformed. Conformity of a URL spec and connection handling are completely separate concerns, and should be handled as such.


Submitted On 04-MAR-2008
bestsss
this is a bug and a bad design
actually TCL may not be used since the instance is kept forever (or at least a URLStreamHandleFactory is installed) in a private Hashtable effectively making the Handler publicly visible (not only to the caller Thread). 
That would prevent any garbage collection and isolation of web-apps, no redeploy, etc.

Most of all that's a very serious bug w/ any application relying on Web Start. Mildly put - they don't work w/o custom URLStreamHandler...



PLEASE NOTE: JDK6 is formerly known as Project Mustang