Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jruby.bash includes current directory in classpath, should not #2783

Closed
derek-upham opened this issue Mar 30, 2015 · 11 comments
Closed

jruby.bash includes current directory in classpath, should not #2783

derek-upham opened this issue Mar 30, 2015 · 11 comments

Comments

@derek-upham
Copy link

The jruby.bash script in jruby-1.7 and jruby-9.0.0.0 sticks the $CLASSPATH environment variable onto the end of the calculated -classpath argument $CP. The concatentation process happens whether or not $CLASSPATH exists:

-classpath "$CP$CP_DELIMITER$CLASSPATH"

This means if you don't specify a $CLASSPATH, -classpath ends up with a trailing colon:

lib/foo.jar:lib/bar.jar:

That trailing colon puts the process root directory into -classpath, whether or not you wanted it there. It's possible to work around this by setting $CLASSPATH to a non-existent file/directory:

env CLASSPATH=/dev/null/does/not/exist jruby.bash

but it seems more appropriate to not put the current directory into -classpath unless you explicitly request it:

env CLASSPATH=. jruby.bash
env CLASSPATH=$(pwd) jruby.bash

I have included a sample patch against jruby-1.7.11 which fixes the problem. It may also apply cleanly to the latest jruby-9.0.0.0 code.


diff --git a/jruby-1.7.11/bin/jruby.bash b/jruby-1.7.11/bin/jruby.bash
index 438d250..5cbecb0 100755
--- jruby-1.7.11/bin/jruby.bash
+++ jruby-1.7.11/bin/jruby.bash
@@ -309,6 +309,10 @@ JAVA_OPTS="$JAVA_OPTS $JAVA_MEM $JAVA_MEM_MIN $JAVA_STACK"

 JFFI_OPTS="-Djffi.boot.library.path=$JRUBY_HOME/lib/jni"

+if test -n "$CLASSPATH"; then
+    CP="$CP$CP_DELIMITER$CLASSPATH"
+fi
+
 if $cygwin; then
   JRUBY_HOME=`cygpath --mixed "$JRUBY_HOME"`
   JRUBY_SHELL=`cygpath --mixed "$JRUBY_SHELL"`
@@ -346,7 +350,7 @@ if [ "$VERIFY_JRUBY" != "" ]; then
     JRUBY_OPTS=''
   fi

-  "$JAVACMD" $PROFILE_ARGS $JAVA_OPTS "$JFFI_OPTS" "${java_args[@]}" -classpath "$JRUBY_CP$CP_DELIMITER$CP$CP_DELIMITER$CLASSPATH" \
+  "$JAVACMD" $PROFILE_ARGS $JAVA_OPTS "$JFFI_OPTS" "${java_args[@]}" -classpath "$JRUBY_CP$CP_DELIMITER$CP" \
     "-Djruby.home=$JRUBY_HOME" \
     "-Djruby.lib=$JRUBY_HOME/lib" -Djruby.script=jruby \
     "-Djruby.shell=$JRUBY_SHELL" \
@@ -369,7 +373,7 @@ if [ "$VERIFY_JRUBY" != "" ]; then
 else
   if $cygwin; then
     # exec doed not work correctly with cygwin bash
-    "$JAVACMD" $JAVA_OPTS "$JFFI_OPTS" "${java_args[@]}" -Xbootclasspath/a:"$JRUBY_CP" -classpath "$CP$CP_DELIMITER$CLASSPATH" \
+    "$JAVACMD" $JAVA_OPTS "$JFFI_OPTS" "${java_args[@]}" -Xbootclasspath/a:"$JRUBY_CP" -classpath "$CP" \
       "-Djruby.home=$JRUBY_HOME" \
       "-Djruby.lib=$JRUBY_HOME/lib" -Djruby.script=jruby \
       "-Djruby.shell=$JRUBY_SHELL" \
@@ -382,7 +386,7 @@ else

     exit $JRUBY_STATUS
   else
-    exec "$JAVACMD" $JAVA_OPTS "$JFFI_OPTS" "${java_args[@]}" -Xbootclasspath/a:"$JRUBY_CP" -classpath "$CP$CP_DELIMITER$CLASSPATH" \
+    exec "$JAVACMD" $JAVA_OPTS "$JFFI_OPTS" "${java_args[@]}" -Xbootclasspath/a:"$JRUBY_CP" -classpath "$CP" \
       "-Djruby.home=$JRUBY_HOME" \
       "-Djruby.lib=$JRUBY_HOME/lib" -Djruby.script=jruby \
       "-Djruby.shell=$JRUBY_SHELL" \

@headius
Copy link
Member

headius commented Mar 30, 2015

We had been adding . to classpath because by default the java command uses . as classpath, and we wanted to mimc that behavior for the jruby command.

[] ~/projects/jruby $ cat Blah.java
public class Blah {
  public static void main(String[] args) {
    System.out.println(System.getProperty("java.class.path"));
  }
}

[] ~/projects/jruby $ javac Blah.java

[] ~/projects/jruby $ java Blah
.

Given this, do you still feel like we should change it?

@derek-upham
Copy link
Author

Okay, I was looking at it from the Ruby side, which doesn't include the current directory by default.

% cp /dev/null foo.rb
% irb 
irb(main):001:0> require 'foo'
LoadError: cannot load such file -- foo
        from /usr/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
        from /usr/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
        from (irb):1
        from /usr/bin/irb:12:in `<main>'
irb(main):002:0> 
% irb -I .
irb(main):001:0> require 'foo'
=> true
irb(main):002:0> 

If you are favoring Java compatibility over Ruby compatibility, then anyone affected by the problem can use the "nonexistent directory" work around to get the current directory out of -classpath.

@mkristian
Copy link
Member

@headius hmm, in the new load-service I put a quite some effort in to not find resources in current directory unless the "." is in $LOAD_PATH. there are a couple of test which check this but they do switch the ruby current directory to somewhere else and then the old load-service does not find it.

well I expected things to be the ruby way - like @derek-upham

@mkristian
Copy link
Member

maybe we should make my "omitted" testcase to test what we want to have.

@enebo enebo added this to the Invalid or Duplicate milestone Apr 28, 2015
@jiamo
Copy link

jiamo commented Sep 5, 2015

Can somebody give a look on https://github.com/compiler-tech/dsl_in_action_ch4_ruby_trade . Why java -cp .:/usr/local/Cellar/jruby/9.0.0.0/libexec/lib/jruby.jar trade_dsl can't work . But jruby -I. trade_dsl.rb can work?

@mkristian
Copy link
Member

@jiamo classpath != load-path

the first sets "." to the classpath and the second sets it to the load-path - two different things. MRI does not to inside "." unless "." is on the load-path. the same jruby does whether it can find files on the classpath or not. jruby will honor the MRI behavior.

@jiamo
Copy link

jiamo commented Sep 5, 2015

@mkristian thanks. In my situation I alreay compile rb files to class files, and add . to classpath, seem it does't concern the load-path?

@mkristian
Copy link
Member

it should be no difference whether the ruby files are compiled or not.
they are from the jruby point of view the same files, i.e. they have to be
on the load-path.

your examples should work like this:

java -cp /usr/local/Cellar/jruby/9.0.0.0/libexec/lib/jruby.jar
org.jruby.Main -I. trade_dsl

maybe even

java -cp .:/usr/local/Cellar/jruby/9.0.0.0/libexec/lib/jruby.jar
org.jruby.Main trade_dsl

did not check out your code so far.

@jiamo
Copy link

jiamo commented Sep 6, 2015

Hi, In my situation, java -cp /usr/local/Cellar/jruby/9.0.0.0/libexec/lib/jruby.jar org.jruby.Main -I. trade_dsl.rb can work, while java -cp /usr/local/Cellar/jruby/9.0.0.0/libexec/lib/jruby.jar org.jruby.Main -I. trade_dsl still can't work, it will cause something like Error opening script file: trade_dsl (No such file or directory)

@mkristian
Copy link
Member

mkristian commented Sep 6, 2015 via email

@jiamo
Copy link

jiamo commented Sep 6, 2015

Thanks, Using java -cp /usr/local/Cellar/jruby/9.0.0.0/libexec/lib/jruby.jar org.jruby.Main -I. trade_dsl.class to get answer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants