13 Replies Latest reply: Oct 28, 2012 1:12 PM by jschellSomeoneStoleMyAlias RSS

    Current Working Directory in Java classpath

    srikanth vallabhaneni
      Can someone explain why the current working directory is getting added to the classpath in these scenarios when I did not include "." in the CLASSPATH?

      http://docs.oracle.com/javase/6/docs/technotes/tools/windows/classpath.html says that current working directory gets added only when CLASSPATH is not set.


      C:\TEMP>set CLASSPATH=;;;



      C:\TEMP>%JAVA_HOME%\bin\java test.Test

      java.class.path=;;;

      classloader:sun.misc.Launcher$AppClassLoader@1cde100

      classloader path:[file:/C:/TEMP/, file:/C:/TEMP/, file:/C:/TEMP/, file:/C:/TEMP/]



      C:\TEMP>set CLASSPATH=



      C:\TEMP>%JAVA_HOME%\bin\java test.Test

      java.class.path=.

      classloader:sun.misc.Launcher$AppClassLoader@1a16869

      classloader path:[file:/C:/TEMP/]



      C:\TEMP>set CLASSPATH=a



      C:\TEMP>%JAVA_HOME%\bin\java test.Test

      Exception in thread "main" java.lang.NoClassDefFoundError: test/Test

      Caused by: java.lang.ClassNotFoundException: test.Test

      at java.net.URLClassLoader$1.run(URLClassLoader.java:202)

      at java.security.AccessController.doPrivileged(Native Method)

      at java.net.URLClassLoader.findClass(URLClassLoader.java:190)

      at java.lang.ClassLoader.loadClass(ClassLoader.java:306)

      at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)

      at java.lang.ClassLoader.loadClass(ClassLoader.java:247)

      Could not find the main class: test.Test. Program will exit.



      C:\TEMP>set CLASSPATH=a;



      C:\TEMP>%JAVA_HOME%\bin\java test.Test

      java.class.path=a;

      classloader:sun.misc.Launcher$AppClassLoader@1a16869

      classloader path:[file:/C:/TEMP/a, file:/C:/TEMP/]



      C:\TEMP>set CLASSPATH=;a



      C:\TEMP>%JAVA_HOME%\bin\java test.Test

      java.class.path=;a

      classloader:sun.misc.Launcher$AppClassLoader@1a16869

      classloader path:[file:/C:/TEMP/, file:/C:/TEMP/a]



      C:\TEMP>
        • 1. Re: Current Working Directory in Java classpath
          EJP
          You've specified an empty CLASSPATH. Probably the wording in the link could be improved, but logically that's equivalent to not setting it at all.
          • 2. Re: Current Working Directory in Java classpath
            srikanth vallabhaneni
            Thank you. I am ok with the empty classpath being interpreted as current working directory. I am talking about other scenarios like "set CLASSPATH=;;;" being treated as current working directory added four times to the classpath.
            • 3. Re: Current Working Directory in Java classpath
              EJP
              That's what I'm talking about. Logically that is still an empty CLASSPATH. Four times nothing is still nothing.
              • 4. Re: Current Working Directory in Java classpath
                srikanth vallabhaneni
                When we are constructing the CLASSPATH variable from other variables, we just concatenate different variables with the path separator to come up with the final path. If any of those variables are empty or if we ended the whole path with a path separator, the current working directory is coming into the classpath. Is it the intent? Users may not even notice that the current working directory is getting added to the CLASSPATH as they are not deliberately adding '.'

                I noticed this behavior when code(in a J2EE WAR in a J2EE EAR) is loading a property file from classpath (and it is working). However the property file is not in the WAR or EAR or anywhere in the application server classpath except that it is in the directory where the application server is getting started(which I later found out is also getting added to the CLASSPATH).

                So any simple misplacement of a path separator character can result in the current working directory getting added to the CLASSPATH. I did not expect this at all.
                • 5. Re: Current Working Directory in Java classpath
                  EJP
                  If any of those variables are empty or if we ended the whole path with a path separator, the current working directory is coming into the classpath.
                  I'd be surprised, in fact I'd be astonished. I would expect that if you put anything into the classpath other than empty elements, it won't use '.'. However this is not what you have done. What you have done is specify four empty elements, which is equivalent to specifying nothing at all, which is causing it to use '.'.
                  Is it the intent? Users may not even notice that the current working directory is getting added to the CLASSPATH as they are not deliberately adding '.'
                  I don't believe it's even happening.
                  So any simple misplacement of a path separator character can result in the current working directory getting added to the CLASSPATH. I did not expect this at all.
                  I think you are misinterpreting what I said.
                  • 6. Re: Current Working Directory in Java classpath
                    srikanth vallabhaneni
                    If you look at the setDomainEnv.cmd of a weblogic domain, you will find this

                    set CLASSPATH=%PRE_CLASSPATH%;%WEBLOGIC_CLASSPATH%;%POST_CLASSPATH%;%WLP_POST_CLASSPATH%

                    If any of these variables is empty or their paths start with or end with ; (path separator) or they have something like this ;; then current working directory can get added to the classpath one to many times.
                    • 7. Re: Current Working Directory in Java classpath
                      EJP
                      As I said above, I don't believe that happens. I believe it happens if the entire CLASSPATH is logically empty, not just elements of it. If you have some counter-evidence, let's have it. Not just more speculation. We're going round in circles here.
                      • 8. Re: Current Working Directory in Java classpath
                        srikanth vallabhaneni
                        I put all this in test.cmd file and ran it from c:\temp; c:\temp\test\Test.class is where the class file is

                        @echo on

                        set PRE_CLASSPATH=

                        set WEBLOGIC_CLASSPATH=C:\bea103\wlserver_10.3\server\lib\weblogic.jar

                        set POST_CLASSPATH=

                        set WLP_POST_CLASSPATH=

                        set CLASSPATH=%PRE_CLASSPATH%;%WEBLOGIC_CLASSPATH%;%POST_CLASSPATH%;%WLP_POST_CLASSPATH%

                        echo %CLASSPATH%

                        c:\bea103\jdk6\bin\java test.Test

                        and this what I see


                        C:\TEMP>test.cmd

                        C:\TEMP>set PRE_CLASSPATH=

                        C:\TEMP>set WEBLOGIC_CLASSPATH=C:\bea103\wlserver_10.3\server\lib\weblogic.jar

                        C:\TEMP>set POST_CLASSPATH=

                        C:\TEMP>set WLP_POST_CLASSPATH=

                        C:\TEMP>set CLASSPATH=;C:\bea103\wlserver_10.3\server\lib\weblogic.jar;;

                        C:\TEMP>echo ;C:\bea103\wlserver_10.3\server\lib\weblogic.jar;;
                        ;C:\bea103\wlserver_10.3\server\lib\weblogic.jar;;

                        C:\TEMP>c:\bea103\jdk6\bin\java test.Test
                        java.class.path=;C:\bea103\wlserver_10.3\server\lib\weblogic.jar;;
                        classloader:sun.misc.Launcher$AppClassLoader@1a16869
                        classloader path:[file:/C:/TEMP/, file:/C:/bea103/wlserver_10.3/server/lib/weblogic.jar, file:/C:/TEMP/, file:/C:/TEMP/]

                        C:\TEMP>
                        • 9. Re: Current Working Directory in Java classpath
                          srikanth vallabhaneni
                          package test;

                          public class Test
                          {
                               public static void main(String[] args)
                               {
                                    System.out.println("java.class.path="+System.getProperty("java.class.path"));
                                    System.out.println("classloader:"+Test.class.getClassLoader());
                                    System.out.println("classloader path:"+java.util.Arrays.toString(((java.net.URLClassLoader)Test.class.getClassLoader()).getURLs()));
                               }
                          }
                          • 10. Re: Current Working Directory in Java classpath
                            srikanth vallabhaneni
                            Mr. EJP,
                            Have you any further comments on this?
                            • 11. Re: Current Working Directory in Java classpath
                              jschellSomeoneStoleMyAlias
                              Your definition of classpath is not precise, which isn't necessarily your problem since it is used to apply to many things.

                              Your code demonstrates that your real question is about the urls of the system class loader.

                              I verified your code output on my system (windows) using 1.7.0_07-b10.
                              And also 1.6.0_12-b04 and even 1.4.0_01-b03.
                              All the same, so the behavior isn't new.

                              Conversely the java.class.path output demonstrates that the "classpath" per that description doesn't really resolve to anything meaningful.

                              I would say that myself I find the implementation which adds multiples certainly not ideal. Although one might suppose that in the actual resolution that it optimizes that away (but then why not do it originally anyways?)
                              user623867 wrote:
                              Can someone explain why the current working directory is getting added to the classpath in these scenarios when I did not include "." in the CLASSPATH?
                              In terms of the class loader - because it is coded that way.

                              It has been that way for a long time so it doesn't matter to a lot of people. Resolution is based on the first find so it would only ever be a problem if you were not finding classes. And doing that a lot. That isn't a typical situation. And only then if isn't somehow not optimizing it.

                              If it is a problem for you then you can replace the system class loader using java VM command line options. You can also replace the URLClassLoader
                              • 12. Re: Current Working Directory in Java classpath
                                srikanth vallabhaneni
                                Thank you for the reply. My main issue is that folks may not be even aware of the fact that the current working directory is getting added to the classpath (as they did not explicitly put '.' in the classpath). At least I did not know until I recently started looking at some code where a property file is getting loaded from the classpath and the property file is no where in the J2EE WAR/EAR or any classpath hierarchy of the application server but it is in the directory where the app server is getting started.

                                Now that I know that current working directory can be added automatically in certain cases (by a simple misplacement of a path separator character), I can better troubleshoot any classloading issues. Obviously, we can override the classloader hierarchy to control where things are loaded from etc. Before, I did not even think of looking at current working directory (as '.' is not in the classpath explicitly); now that I know, I will start looking in current working directory also.
                                • 13. Re: Current Working Directory in Java classpath
                                  jschellSomeoneStoleMyAlias
                                  user623867 wrote:
                                  Thank you for the reply. My main issue is that folks may not be even aware of the fact that the current working directory is getting added to the classpath (as they did not explicitly put '.' in the classpath).
                                  Except of course that I have shown that this has been going on for years and this is the first time anyone noted it. Thus it would suggest that regardless of the lack of knowledge it is not a problem. Not a problem for a lot of people.

                                  At least I did not know until I recently started looking at some code where a property file is getting loaded from the classpath and the property file is no where in the J2EE WAR/EAR or any classpath hierarchy of the application server but it is in the directory where the app server is getting started.
                                  That to me sounds like an install problem.