0

I'm trying to build a jar file that includes the MySQL driver for JDBC. So far I have a very basic build.gradle file that is using the shadowJar plugin to help build this jar file.

The problem is, when running anything Gradle related, I receive this error:

ERROR: JAVA_HOME is set to an invalid directory: /usr/lib/jvm/jdk-11.0.1/bin/java

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation.

When trying to locate Java with $ which java I get

/usr/bin/java

and with $ ls -la /usr/bin | grep -i javaj I receive

lrwxrwxrwx  1 root     root          22 Sep 21 11:32 java -> /etc/alternatives/java
lrwxrwxrwx  1 root     root          29 Nov  5 21:12 java2groovy -> /etc/alternatives/java2groovy
lrwxrwxrwx  1 root     root          23 Nov  5 20:33 javac -> /etc/alternatives/javac
lrwxrwxrwx  1 root     root          25 Nov  5 20:33 javadoc -> /etc/alternatives/javadoc
lrwxrwxrwx  1 root     root          23 Nov  5 20:33 javah -> /etc/alternatives/javah
lrwxrwxrwx  1 root     root          23 Nov  5 20:33 javap -> /etc/alternatives/javap

So far none of this information has been helpful for me but I'm leaving it here just in case.

Also, when I use $ readlink -f $(which java) I receive:

/usr/lib/jvm/jdk-11.0.1/bin/java

Which to me seems like it is the appropriate path that Gradle is trying to look.

Lastly, in my .bashrc I have put this in the file to set my JAVA_HOME:

## JAVA ##
export JAVA_HOME="/usr/lib/jvm/jdk-11.0.1/bin/java"
export PATH=$PATH:/usr/lib/jvm/jdk-11.0.1/bin

Any ideas on why running $ ./gradlew shadowJar would not be able to find Java?

Edit

According to this question which seems similar to my question, my version of Gradle is trying to set its own JAVA_HOME path which I've figured out it is being set to /usr/bin/java/bin/java which does not exist.

On lines 70 - 89 there is an if/else statement doing this enter image description here

Brandon Benefield
  • 1,504
  • 1
  • 21
  • 36
  • This is more suited for a general Linux/Unix SE. But if you are on a system that supports "alternatives", you should use that to make sure the appropriate packages are installed, and then have JAVA_HOME, et al, point to the alternative locations, not necessarily the brittle inner location. At no point here to you actually _test_ that the Java runtime and compiler in that inner location is actually present, and actually runs. Also, just because a link is present doesn't mean it is actually a valid location. –  Dec 05 '18 at 20:28
  • In short, I think this really belongs on https://unix.stackexchange.com/ or one of the Linux distro specific SEs. I suspect this is already answered over there. –  Dec 05 '18 at 20:33
  • @jdv I appreciate the comments, I'll go ahead and take a look over at unix.stackexchange.com as well but in the meantime are you suggesting I should set my `JAVA_HOME` path to the `/usr/bin/java/` which points to `/etc/alternatives/java` which then points to `/usr/lib/jvm/jdk-11.0.1/bin/java`? Lastly, how would you like me to test that java and javac run correctly? Running both `$ java --version` and `$ javac --version` both return `11.0.1` for their respective installations. – Brandon Benefield Dec 05 '18 at 21:25
  • 1
    Oh wait. JAVA_HOME should be a directory, right? You have it set to an executable. Set it to `/usr/lib/jvm/jdk-11.0.1` directly in the shell and try again. This is suggested by your latest update, as well. Ignore my nonsense about JAVA_HOMEset to /usr/lib or whatever as that is... nonsense. In my defense: it has been a long day. –  Dec 05 '18 at 21:44
  • @jdv worked like a charm. I did this directly in the terminal. The only thing I'm not sure of is how to point my `JAVA_HOME` to the alternatives directory when that is actually pointing to the executable and now the directory that contains it. – Brandon Benefield Dec 05 '18 at 21:47
  • Yeah, that was me creating your confusion. When using JAVA_HOME you have to find where it actually is, and commit to setting it to a specific release of the JVM or JDK (in this case, for Gradle, make sure it points at a JDK.) The alternatives offer the convenience for running Java commands and managing versions to some extent. Maybe it offers a JAVA_HOME like hook? I'd have to read the man pages. I actually prefer the "SDKMan" method (a web search will reveal all) for versioning VMs and Java tooling, though that isn't everyone's cup of tea. –  Dec 05 '18 at 22:00
  • And, to clarify. Now that you know it works, you can create startup scripting to your heart's content that will set JAVA_HOME to whatever you like. I've experimented with "sourcing" scripts that set this stuff in the current shell for me, so I can have one version for some project, and another version for another. But the takeaway is all apps that use JAVA_HOME will expect to tag `/bin/java` onto the end and have a executable that does the right thing. This won't happen with basic alternatives setup. There may be advance alternatives stuff that Does The Right Thing, though. –  Dec 05 '18 at 22:05

1 Answers1

2

Instead of hiding the solution in comments, I'll create an answer. This is marginally on-topic since it has to do not only with how JAVA_HOME is set on a Linux/POSIX system, but also how the Gradle Wrapper behaves different than a given Gradle executable.

In this manner it is related to, but not quite the same as this Q&A which has a lot of nice hints in it.

In a nutshell:

  • The Gradle Wrapper gradlew uses JAVA_HOME if set, otherwise will attempt to just run java without any JAVA_HOME. It'll log to the console about this, and that it can't really continue.
  • JAVA_HOME is always expected to be set to a path that resolves to a directory, not a file.

In this case, JAVA_HOME was set to the actual JDK Java executable, and there was some confusion about the Linux "alternatives" (how multiple packages and package versions can fulfill system requirements) and how those work with JAVA_HOME. (Most of that confusion was me misunderstanding the question!)

This meant that the Gradle Wrapper was (in this case) trying to invoke /usr/lib/jvm/jdk-11.0.1/bin/java/bin/java (note the double ref to "bin/java") as the JAVA_CMD which, of course, doesn't exist.

Once we set JAVA_HOME to the expected JDK location the Gradle Wrapper ran successfully.

AFAIK, the alternatives system does not have any conveniences for providing a JAVA_HOME like reference to the underlying JDK location. I suppose one could script the output from the alternatives command to get the currently installed and active JDK location.