5

I'm currently trying to install ghidra on my Ubuntu 20.04 machine. While installing, I get this:

******************************************************************
JDK 11+ (64-bit) could not be found and must be manually chosen!
******************************************************************
Enter path to JDK home directory (ENTER for dialog): 

So, I think cool, and run:

sudo apt-get install openjdk-11-jdk

If I now run whereis java:

/usr/share/java$ whereis java
java: /usr/bin/java /usr/share/java /usr/share/man/man1/java.1.gz

So I cd to the first directory, ans look:

/usr/share/java$ ls
commons-logging-1.2.jar           java-atk-wrapper.jar  pdfbox-1.8.16.jar
commons-logging-adapters-1.2.jar  java_defaults.mk      pdfbox.jar
commons-logging-adapters.jar      java_uno.jar          ridl-6.4.7.jar
commons-logging-api-1.2.jar       juh-6.4.7.jar         ridl.jar
commons-logging-api.jar           juh.jar               unoloader-6.4.7.jar
commons-logging.jar               jurt-6.4.7.jar        unoloader.jar
fontbox-1.8.16.jar                jurt.jar
fontbox.jar                       libintl.jar

Here is a bunch of jar files? Usually the jdk has a bin folder and so on?

I also try giving /usr/share/java to the ghidra installation, but it complains that this is not a valid jdk home directory because it is missing a bin folder.

Kevin Bowen
  • 19,615
  • 55
  • 79
  • 83

3 Answers3

4

First, make sure the installation was done correctly by running java --version, you should see something like: enter image description here

Then, in order to locate the jdk folder, run the command below:

readlink -f $(which java) 

It returns the path, in my case it returns:

/usr/lib/jvm/java-11-openjdk-amd64/bin/java

you can run ls /usr/lib/jvm/java-11-openjdk-amd64 and it will show the jdk folder content. It'd look something like: enter image description here

Details

Why

First whereis! Just like which doesn't resolve symlinks!

which java => give Command path => return a symlink to a symlink

Example in debian:

/usr/bin/java =symlink to=> /etc/alternatives/java =symlink to=> /usr/lib/jvm/java-10-openjdk-amd64/bin/java

/usr/lib/jvm/java-10-openjdk-amd64/bin/java is the actual java binary! And /usr/lib/jvm/java-10-openjdk-amd64 is the java home.

If you want to use whereis! One need to resolve the symlinks too! And here recursively!

Symlink => Symlink => Actual folder or file

We can do that through read link

Readlink

https://man7.org/linux/man-pages/man1/readlink.1.html

https://www.geeksforgeeks.org/readlink-command-in-linux-with-examples/

readlink - print resolved symbolic links or canonical file names

In short! if you have a symbolic link!

readlink symbolicLink => Will give what it resolve to

given Symlink1 => Symlink2 => path

readllink Symlink1 =return=> Symlink2

readlink Symlink2 =return=> path`

Here let's see it with java:

enter image description here

A one command

enter image description here Yup that's ugly!

And there is better! Use the -f flag

from the help doc

 -f, --canonicalize            canonicalize by following every symlink in
                                every component of the given name recursively;
                                all but the last component must exist

So:

readlink -f $(which java)

Recursivly resolve the symlinks!

enter image description here

You can use that through whereis too!

enter image description here

You can see and can find your home directory!

Using which in this context! Is better then whereis!

For the difference between which and whereis! Let's use whatis

$  whatis which
which                (1)  - shows the full path of (shell) commands

$ whatis whereis whereis (1) - locate the binary, source, and manual page files for a command

2

Since you have previously checked with whereis whether your binary is installed,
now you can check if it can be executed properly :

  • does its location belong to your PATH variable ? try the command which java and it should return something like /usr/bin/java

  • is it a valid binary then ? try to display its version using the command java -version and it should display something like

openjdk version "11.0.11" 2021-04-20
OpenJDK Runtime Environment (build 11.0.11+9-Ubuntu-0ubuntu2.20.04)
OpenJDK 64-Bit Server VM (build 11.0.11+9-Ubuntu-0ubuntu2.20.04, mixed mode, sharing)
  • also keep in mind that some java applications may need to set the JAVA_HOME environment variable. Then you can set it to the home dir of your java install, for example JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64

To help you to retrieve the java home path you can use which java | xargs realpath which provides a path like /usr/lib/jvm/java-11-openjdk-amd64/bin/java (or you can use ls -l several times on the path provided by which) from which you need to remove the latest part /bin/java.

PS : be careful with the fact that if you need several java runtimes on your system, then the PATH resolution and the JAVA_HOME must match to the same version.
At your convenience, you can unzip any specific version in any folder like /my/custom/install/jdk15/ and override the system paths :

  export JAVA_HOME=/my/custom/install/jdk15
  export PATH=$JAVA_HOME/bin:$PATH

On my system I set JAVA_HOME inside my .bashrc using a command that looks like this :

export JAVA_HOME=`dirname $(dirname $(readlink -f $(which java)))`
export PATH=$JAVA_HOME/bin:$PATH
1

An alternative to whereis and find command is the locate command. It is extremely fast:

$ locate openjdk | head -n10
/home/rick/Android/Sdk/sources/android-28/org/openjdk
/home/rick/Android/Sdk/sources/android-28/org/openjdk/testlib
/home/rick/Android/Sdk/sources/android-28/org/openjdk/testlib/java
/home/rick/Android/Sdk/sources/android-28/org/openjdk/testlib/java/util
/home/rick/Android/Sdk/sources/android-28/org/openjdk/testlib/java/util/stream
/home/rick/Android/Sdk/sources/android-28/org/openjdk/testlib/java/util/stream/CollectorOps.java
/home/rick/Android/Sdk/sources/android-28/org/openjdk/testlib/java/util/stream/DoubleStreamTestDataProvider.java
/home/rick/Android/Sdk/sources/android-28/org/openjdk/testlib/java/util/stream/DoubleStreamTestScenario.java
/home/rick/Android/Sdk/sources/android-28/org/openjdk/testlib/java/util/stream/FlagDeclaringOp.java
/home/rick/Android/Sdk/sources/android-28/org/openjdk/testlib/java/util/stream/IntStreamTestDataProvider.java

These are the first 10 filenamess containing openjdk. You can quickly locate and count the number of files using wc (word count) command with the -l (line count) parameter:

$ time locate java | wc -l
57555

real 0m0.945s user 0m0.927s sys 0m0.021s

$ time locate openjdk | wc -l 72

real 0m1.053s user 0m1.033s sys 0m0.021s

So there are 57,555 files withjava in the filename and 72 files with openjdk in the filename. In both instances it takes about 1 second to find them all.

To truly appreciate the speed of the locate command consider searching which filenames contain the letter e which is the most common letter in the alphabet:

$ time locate e | wc -l
2283738

real 0m0.580s user 0m0.592s sys 0m0.177s

There are 2,228,738 files with the letter e occuring at least once in their filename. This is for three Ubuntu installations, one Windows installation and one shared Ubuntu + Windows partition. It only takes 1/2 a second to locate them!

You may have to install the locate command first: