This week's book giveaway is in the Spring forum. We're giving away four copies of Pro Spring MVC with WebFlux: Web Development in Spring Framework 5 and Spring Boot 2 and have Marten Deinum & Iuliana Cosmina on-line! See this thread for details.
I run a DashO obfuscated web application in Tomcat 4.1.18 on Win2K, and I get the following: java.lang.NoClassDefFoundError: javax/servlet/http/HttpServletRequest at au.a(DashoA8050) at com.project.servlet.LoginServlet.processRequest(DashoA8050) at com.project.servlet.LoginServlet.doPost(DashoA8050) at javax.servlet.http.HttpServlet.service(HttpServlet.java:760) at javax.servlet.http.HttpServlet.service(HttpServlet.java:853) I run the same web application, but without the obfuscation, and no problems. DashO, the build, and Tomcat are all run with the same Java, and are all using the same servlet.jar file. I have verified all classpaths, and the jar file does include the needed classes, and it is the only jar file that includes that package. I don't see why HttpServletRequest would not be found, when it just found HttpServlet from the same package. Any ideas?
FYI - Discovered this cached post which helped me resolve the issue - I moved the jars from the tomcat/common/lib folder to the tomcat/lib folder and it worked fine. Not sure why it didn't work when I had the jar files referenced directly in the classpath. ------------------- [jcifs] More classloader issues Glass, Eric firstname.lastname@example.org Fri, 13 Dec 2002 16:27:15 -0500 Previous message: [jcifs] More classloader issues Next message: [jcifs] More classloader issues Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] -------------------------------------------------------------------------------- > > I don't understand. If Webapp1 tries to access an SmbFile that will > execute the static initializer in jcifs.Config which will add > 'jcifs' to > the java.protocol.handler.pkgs System property. The jCIFS > classes should > be available to the System class loader (that's our requirement). When > the SmbFile constructor is called, the URL class (loaded from the > System class loader) will see 'smb://' and try to find a handler. From > the code you show below it should find jcifs.smb.Handler in the System > class loader. Everything ok so far right? >
This is correct -- with jCIFS loaded from the system classloader, a servlet would be able to use SMB URLs properly as described above. This will solve the MalformedURLExceptions when attempting to create SMB URLs under both Tomcat and Resin (under just about any environment, actually). Tomcat's issue is different, but somewhat related.
> > > > The problem will arise under Tomcat when NtlmFilter is > loaded; it will find > > the implementation under the system classloader, but > NtlmFilter will be > > unable to find javax.servlet.Filter (which is loaded under > the common > > classloader). This will cause a NoClassDefFoundError, specifically: > > But the container will be trying to load classes in the Webapp class > loader. So when accessing jcifs.http.NtlmHttpFilter it will fail as it > will in the Shared and Common class loaders before > successfully loading > from the System class loader. Now when resolving the > javax.servlet.Filter > baseclass and other servlet classes will it try from the Webapp > classloader again or degenerate to the classloader from which it just > loaded jcifs.http.NtlmHttpFilter? I don't see the security risk in > starting from the original context loader again.
It's not as much a matter of security as it is visibility; what happens is: a) The container tries to load jcifs.http.NtlmHttpFilter via the webapp classloader. b) The webapp classloader fails (since jCIFS is installed in the system classloader); classloading is delegated to the parent (the "shared" classloader). c) The shared classloader fails, and classloading is delegated to the parent (the "common" classloader). d) The common classloader fails, and classloading is delegated to the system classloader. e) The system classloader successfully locates jcifs.http.NtlmHttpFilter, and begins to define the class. f) As part of the class definition process, the system classloader attempts to locate and load the superclass (javax.servlet.Filter). This process is independent of the loading of NtlmHttpFilter; the system classloader is unaware of the existence of the descendant classloaders (common, shared, and webapp). Since the system classloader is the defining classloader for NtlmHttpFilter, that is where the search begins (and, as it turns out, ends with a failure). This is kind of a simplification; in reality only the webapp classloader attempts to load the class before delegating to the parent (the normal JDK behavior is to delegate to the parent first, and load the class only if the parent cannot find it; the servlet spec reverses this behavior for the webapp classloader to allow web applications to override container-wide classes). But the end result is the same; webapp fails, and delegates to shared, which delegates to common, which delegates to system, which succeeds. While defining the NtlmHttpFilter class, system attempts to load javax.servlet.Filter, and fails. Basically each classloader is only aware of its parent, and has no means of knowing if any child classloaders exist.
> > Also getting jcifs.smb.Handler installed in the System class loader is > a completely separate issue right? There's really no relation between > the problems other than their both being "class loading" issues. >
That is correct, with the caveat being that putting jcifs.smb.Handler in the system classloader also puts NtlmHttpFilter in the system classloader (since they are packaged together), which causes the Tomcat issue. To resolve it, Tomcat users have to make sure that the core servlet classes are available in either the same classloader as jCIFS or an ancestor; this involves leaving jcifs.http.* under the webapp classloader (as a separate jar) or moving "servlet.jar" into the system classloader with the jCIFS jar.
> > Ok, this is good info but I don't think it will ever be necessary. Our > requirement is that the jCIFS jar be available to the System > classloader. This basically equites to putting it in the > containers top > level lib directory and possibly adding it explicitly to the container > CLASSPATH. Whatever the case, the code will likely have AllPermission > or similar.
Probably a safe assumption.
> I just need to establish the simplest "correct" installation > procedure. So > far, ensuring the jar is loaded by the System class loader > and that it's > codeBase has the necesary PropertyPermission should work. If > anyone wants > a more finely grained procedure they can be referred to these messages > in the archive. >
Possibly a note for Tomcat users to relocate the servlet.jar, or a note to see the FAQ. Other than that, this should suffice.
I know you already posted the answer, but I'm puzzled as to why you want to use obfuscation anyhow. The clients have no access to any of the .class files or JSP source code, so what's the point of obfuscation? - Marty