JDK-4474172 : JavaWebServer can not be started with B69
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 1.4.0
  • Priority: P1
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2001-06-25
  • Updated: 2001-07-26
  • Resolved: 2001-07-18
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.
Other
1.4.0 beta2Fixed
Related Reports
Relates :  
Relates :  
Description
With Merlin b69, JavaWebServer Server can not be started with the exception:
java.lang.ClassCircularityError: com/sun/server/security/ServletClassLoader
        at com.sun.server.security.ServletSecurity.inServlet(ServletSecurity.jav
a:115)
        at com.sun.server.security.ServletSecurity.checkPackageAccess(ServletSec
urity.java:612)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:265)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:260)
        at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)
        at com.sun.server.security.ServletSecurity.inServlet(ServletSecurity.jav
a:115)
...

The failure happens on all platforms: Solaris Sparc/X86, Linux and Windows.



To start JWS server:
1. telnet jtgb4u2b
2. cd /bt/JavaWebServerrun.3541.-server
3. cp /home/junzhong/env.ksh .
4. $JAVA ${JWSPROPS} com.sun.server.ServerProcess

The exception will be thrown after step 4.

june.zhong@eng 2001-06-25

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: merlin-beta2 FIXED IN: merlin-beta2 INTEGRATED IN: merlin-beta2 VERIFIED IN: merlin-beta2
14-06-2004

EVALUATION This is probably a bug in Java Web Server's classloaders, uncovered because of the switch over to a pure-Java implementation of reflection. I suggest this is a bug in the application because a substantial amount of testing has been performed on the pure-Java version of reflection; recall that a similar bug was found in Cloudscape. I don't know if Java Web Server is still developed, but the developers should take a look at this bug. I suggest using Tomcat instead of Java Web Server as a big app. kenneth.russell@eng 2001-06-26 Gilad.Bracha@eng and I have discussed this bug at length and analyzed the cause together: 1. The generated bytecodes (invoked by a class loaded by the application class loader) attempt to reference the target class (call it "Service"); we go down into the virtual machine. 2. Since the class loader of the generated bytecodes isn't the application class loader, we make an upcall to load the Service class. 3. The DelegatingClassLoader delegates the loading of the Service class to the application class loader. 4. The application class loader performs a security check involving the "inServlet()" method, which performs an instanceof check on the "current" class loader against ServletClassLoader. 5. ServletClassLoader is not yet loaded at this point. We go down into the VM to load it, installing a placeholder in the system dictionary and making an upcall to load it. 6. The application class loader causes a security check to be performed, causing the instanceof check to occur again. We attempt to resolve ServletClassLoader again, resulting in a ClassCircularityError since there is already a placeholder for the Service class in the system dictionary. The difference caused by the new bytecode-based reflection implementation is (2). Bytecode stubs which implement Method.invoke(), Constructor.newInstance(), and Field.set/get() are loaded into newly- fabricated classloaders so the stub code can be GCd when the reflective objects become unreachable (as opposed to staying alive as long as the target class, which could potentially increase footprint significantly). These new classloaders delegate to the defining loaders of the classes being reflected upon to be able to resolve class, method and field references in the dynamically-generated stubs. The old native code reflection implementation did not rely on classloading at all. The fact that an upcall to Java for class loading occurs during reflective operations, where one did not occur before, exposes bugs in brittle classloaders. 4425665 was a bug in Cloudscape's classloader (since fixed by them) where they needed to call findLoadedClass before attempting to re-load a class; this bug (4474172) occurs because ServletClassLoader is not loaded early enough in Java Web Server's startup process, and if class loading is performed before it is loaded then there is a (pre-existing) circularity bug. Unfortunately this is a compatibility issue because it is clear that causing class loading to occur at previously-unexpected times can lead to all kinds of errors in class loaders. As Gilad.Bracha@eng points out, a ClassLoader implementation is hard to get right, and it is not possible to reason about all of the kinds of errors that may occur. If 4425665 and 4474172 have come up during the beta cycle then more are bound to appear later. We considered two options. One would be a new system property which, when specified, would load the reflective stubs into the defining loaders of the classes being reflected upon, at the expense of being able to GC the stub classes if they become unused before the target classes. This has been tested and solves the problem. The advantages of this solution are that it is small, implementable in the Java programming language, and portable among JVM implementations; the disadvantage is that it is not an automatic solution and requires the user to "try this flag" if their application doesn't work. Gilad.Bracha@eng and Rene.Schmidt@eng point out that there are dozens of such "exceptions" in the Java platform already and that a better solution would be automatic. The second solution is to make the virtual machine "magically" delegate class loading for these newly-fabricated class loaders to their parent loaders, without making an upcall to Java. The disadvantage is that this is another hack in the JVM, but there are already two such hacks in place for the new reflection implementation (one disabling security checks to be able to implement AccessibleObject.setAccessible(), and one to disable verification to be able to implement serialization using bytecodes.) The advantages are that the hack is relatively small and requires no user intervention or code changes. This option has been chosen. After implementing the above fix it was discovered that the 1.1 security code had to be modified to perform this "automatic delegation" as well in order to properly identify trusted class loaders on the stack. This in some sense is the analogue of the earlier modifications to the VM to skip the frames associated with MethodAccessorImpl classes (the implementing classes of Method.invoke()), which had not previously been present with the native code reflection implementation. kenneth.russell@eng 2001-07-13
13-07-2001