Java Setup — macOS and Windows

Lana Begunova
15 min readNov 5, 2023

--

Selenium ceases support for Java 8.

Selenium 4.14 or higher only supports Java 11. Source: Titus Fortner in this video.

Selenium 4.15 is already out! (at the time of writing this story)

It’s the best time to check and update our Java environment.

There’s no better time to check and update our test environment setup for the web and mobile automation.

In the context of Appium and Selenium automation, we think about how we would get a working setup on our local machine. The first thing we want to make sure is present is something called Java. Java is a programming language and set of tools that are used by both Appium and Selenium. First of all, we can check to see if we already have Java on our machine. It often comes on computers by default nowadays, or we may have already installed it for another purpose. To check if we have it installed, let’s open up either a terminal on macOS, or a command prompt on Windows, and run the appropriate echo command here:

  • Mac: echo $JAVA_HOME
  • Win: echo %JAVA_HOME%

For Mac, we would get output that looks something like this:

/Library/Java/JavaVirtualMachines/openjdk-11.jdk/Contents/Home

Or this:

/usr/local/Cellar/openjdk@11/11.0.18/libexec/openjdk.jdk/Contents/Home

Whereas for Windows, it looks like:

C:\Program Files\Java\jdk-11.0.21

What do we do, if nothing gets printed out. What are we actually doing anyway? What is the point of these commands? On each platform, these commands are designed to print out the value of something called environment variables.

Let’s take a quick detour to understand environment variables since they’re important, especially, for getting Appium set up. Environment variables are just like variables in any programming language, like Python or Ruby. They are little names that can hold values, and can change over time. Environment variables are designed to be variables that exist in the terminal, or across our whole system. Environment variables are made available to any program that we run from the terminal session where the variable is defined. And we probably already have lots of environment variables set by default, without realizing it.

For example, if we’re on a Mac, we open up a terminal and type echo $HOME. We should get back something that looks like /Users/lanabegunova.

Or, if we’re on Windows, we open up a command prompt and type echo %HOMEPATH%. We should get back something that looks like \Users\begun, based on the specific user’s computer's username.

On either platform, what’s going on is that the path to our home folder has been saved as an environment variable. Here are a couple more key points about environment variables:

  1. Environment variables are only valid in the terminal session where they are defined. If we define an environment variable in one terminal window, and then open up another one, the variable will not exist in the other one. There is a way to make variables persist across sessions.
  2. To check the value of the environment variable, we can use the echo command. On a Mac, we put a dollar sign in front of the variable name (Mac: echo $JAVA_HOME). On Windows, we put percent signs around the variable name (Win: echo %JAVA_HOME%).
  3. To set environment variables from the terminal, we can use the export command on a Mac, or the set command on Windows. For example, we can run export HELLO=world on macOS, or set HELLO=world on Windows. In either case, we do not use the dollar sign or percent signs when assigning values to the variables.

Let’s put words to action now and run the export command first:

export HELLO=world

The command defines the variable HELLO. And now we can try echoing it out, by ensuring that we use the dollar sign when we reference the variable:

echo $HELLO

And sure enough we get world printed out.

But let's try something. We'll open up a new terminal window, and run the same echo command. What happens now?

Variables don’t span multiple sessions. It’s a hurdle to set them by hand every time we open a terminal window. To make them persist, we define environment variable exports in the file with shell startup scripts — .bashrc, .zshrc or even .zprofile.

We get nothing printed out, which means the variable is not defined. That's because our export command only set the variable in that particular terminal session. Variables don't span multiple sessions.

But It’s often really important to have environment variables set for one reason or another, and it’s a pain to set them by hand every time we open a terminal window. So let’s talk about how to make it seem like we can persist these variables across sessions. On Mac, it looks like adding the export command we just saw to something called a shell startup script. By the way, when we say shell, that’s just another way of talking about the program we use when opening up the terminal.

Whenever we open up a shell, the shell process tries to read certain files, called startup scripts, to check if we have put any commands in those files for it to run automatically. We can include environment variable exports in these shell startup scripts. The tricky part is figuring out which file we need to create or edit in order to have it work.

On macOS, the file we can create or edit will depend on our operating system. If you have a version older than Catalina, then the file will be called .bashrc. That . in front makes it a hidden or invisible file, and it needs to be located in our home directory.

It's called bashrc because it's a startup script for the Bash shell, which is the default in older versions of macOS. To figure out if this file exists, we can run the following command: ls ~/.bashrc. On Mac and Linux, the tilde ~ character is a shortcut to our home directory, so this is basically asking the system to list the file called .bashrc in the home directory.

On Catalina or higher, the default shell for macOS is something called Zsh or Z shell, and its startup script file is .zshrc instead.

So basically, look for a ~/.bashrc or a ~/.zshrc file as appropriate for your version of macOS.

To verify if we have a shell on our machine, run command echo $SHELL. If the output is not /bin/zsh, run command chsh -s /bin/zsh to switch to Z shell (zsh). Then navigate to the home directory with cd ~ and create a .zshrc file with the touch .zshrc command. Open the created file with open .zshrc.

We use .zshrc in this demo, hence substitute it with .bashrc for your case if necessary. If we get a filename listed as the output of that ls command, that’s good news.

% ls ~/.zshrc
/Users/lanabegunova/.zshrc

Otherwise, if the .zshrc file does not exist in our home directory, no problem - we just need to create one as described above. Go ahead and load that file. If there's other text in the .zshrc file already, just ignore it for now, it's fine. What we want to do is to create a new line at the very bottom:

export HELLO=world

Now let’s save the file, and close any open terminal windows. Open a new terminal, and run a special source command source ~/.zshrc. The primary use of source command is to refresh environment variables.

Restart the terminal, and try the echo $HELLO command again. Now, it should print out world, and it should do that in the future as well.

So that's how we set environment variables automatically for future terminal sessions on macOS.

On Windows, it’s a bit different, and it’s best to use the system UI to make this change. First, we open up a command prompt however, and try to echo the variable to show that it’s not yet set:

echo %HELLO%
%HELLO%

Remember on Windows that when we refer to environment variables, we put percent signs around them. Now let’s set up this custom environment variable. First, we open up the Start menu and start searching for ‘Advanced system settings’. We can shortcut the search string to ‘env’.

Open the Start menu and search for ‘Advanced system settings’ or ‘env’.

Now we can open up that control panel item, and it will go straight to the ‘advanced’ tab of the system properties control panel. Towards the bottom, we see a button that says “Environment Variables…”.

That’s what we want, so click it. In the window that pops up, we’ll see two sections, one section for user variables and one section for system variables. If we only care about setting these things up for a single user, it’s fine to focus on the user variables, otherwise, focus on the system variables.

Let’s create a new user variable by clicking “New…” underneath that section. This opens up a dialogue where we can enter a name and a value. Enter “HELLO” as the name and “world” as the value, then click OK.

Now, save and exit out of all the dialogues, and open up a new command prompt.

Click OK.
Click OK.
Open a new command prompt.

In the command prompt, we can again type echo %HELLO% and we should see 'world' printed back to us. So that's how we set environment variables persistently on Windows.

Let’s get back to making sure we have Java set up. Remember, the commands we ran to see if it was accessible via the right environment variable are echo $JAVA_HOME on Mac or echo %JAVA_HOME% on Windows. If you got a value printed out there, examine it. Does it have the string "jdk" somewhere in it? And is the version number 11.0 or higher? If so, that’s great! It appears Java is already set up correctly.

% echo $JAVA_HOME
/usr/local/Cellar/openjdk@11/11.0.21/libexec/openjdk.jdk/Contents/Home
% echo %JAVA_HOME%
C:\Program Files\Java\jdk-11.0.21

What if we got something printed out, but it doesn’t say “jdk”? Maybe it says “jre”. In that case we’ll need to download and install a new version of Java. This is because Appium, for example, needs to have something called the JDK, or the Java Development Kit, because this version of Java has more tools bundled with it than the JRE, or the Java Runtime Engine alone. Likewise, if we got nothing printed out at all, then we’ll need to install Java.

The standard way to install Java is to head to java.com/download and follow the instructions for our platform. However, this takes us through a convoluted series of pages and clicks. So instead, head directly to https://www.oracle.com/java/technologies/javase-downloads.html#javasejdk, which is a long link but will save you some time. We need to download and run an installer for the JDK from that page. Ensure it’s the JDK and not the JRE. When you run the downloaded installer, make a note of where you install Java, because we’re going to need that information. Let’s go ahead and install Java 11 on Windows.

Click on the binary of choice and download it.
We may be prompted to create an Oracle account, if we do not have one yet.
Save the downloaded archive/zip file to the location of your choice.
Extract/unarchive the zip folder.
Open the unzipped folder and move the jdk-11 subfolder to the Program Files directory. It’s okay to have multiple versions of Java on the same machine.

Now that we’ve installed Java, we need to set the special JAVA_HOME environment variable. And when we say set the environment variable, we mean going through the steps appropriate for our system that were demonstrated earlier. So on Windows, we do this again by opening up the environment variables area of the advanced system settings, creating a new variable called JAVA_HOME, and as the value setting the path where we installed Java. For example, C:\Program Files\java\jdk-11.0.21 .

Open up the Start menu and start searching for ‘Advanced system settings’ or ‘env’.
Open up that control panel item, and it will go straight to the ‘advanced’ tab of the system properties control panel. Towards the bottom, we see a button that says “Environment Variables…”.
Open up the environment variables area of the advanced system settings.
Create a new variable called JAVA_HOME, and as the value set the path where we installed Java. For example, C:\Program Files\java\jdk-11.0.21 .

On macOS, it’s a bit different. We know how to set environment variables in our .zshrc file now, but how do we know where Java was installed? To figure that out it's easiest to use a little helper program that comes with Java. So we can open up a terminal and run the command /usr/libexec/java_home. For me it prints out:

/usr/local/Cellar/openjdk@11/11.0.21/libexec/openjdk.jdk/Contents/Home

For you it might look different.

/Library/Java/JavaVirtualMachines/openjdk-11.jdk/Contents/Home

Regardless, that is the path we should use as the content of the JAVA_HOME variable. Notice that on macOS, it also looks a bit different than on Windows, because it includes a Contents and a Home directory. But we’ll take this string, open up our .zshrc file, and create the appropriate export statement at the end:

export JAVA_HOME=/usr/local/Cellar/openjdk@11/11.0.21/libexec/openjdk.jdk/Contents/Home

With any export command, there’s something we need to be aware of. If there are any spaces in it, we need to put the value in quotes. In fact, it’s safe to always put things in quotes so it’s not a bad idea to do that. Let’s update our variable to use quotes for safety:

export JAVA_HOME="/usr/local/Cellar/openjdk@11/11.0.21/libexec/openjdk.jdk/Contents/Home"

Now we have JAVA_HOME set on macOS as well.

Next, we’re going to work with yet another environment variable. This one is called PATH. The purpose of the PATH environment variable is to define a list of directories. These directories are the ones our shell will look in when we want to execute a command. Why do we need to do this? Just because we have a program somewhere on our computer doesn’t mean we can just type its name to run it from a shell.

Why would we want to run a program by its name rather than by a full path? Because some programs are so useful we end up using them in lots of places, and it would be tedious to have to type out the full path all the time.

The Java JDK comes with a lot of little programs. For tools like Appium, It makes life easier to have all these little programs on our PATH. So the first step is figuring out where these little programs live. First, let’s check out what’s inside our Java directory, by running a command that allows us to list the contents of a directory. On macOS, this is the ls command, which we can use in conjunction with our newly set environment variable:

ls $JAVA_HOME
bin conf demo include jmods legal lib man release

Now there’s everything that’s inside of JAVA_HOME.

Or on Windows, we use the dir command to do the same thing:

dir "%JAVA_HOME%"

Volume in drive C is OS
Volume in drive C is OS
Volume Serial Number is B08A-2871

Directory of C:\Program Files\Java\jdk-11.0.21

11/05/2023 12:24 AM <DIR> .
11/05/2023 12:27 AM <DIR> ..
11/05/2023 12:24 AM <DIR> bin
11/05/2023 12:24 AM <DIR> conf
11/05/2023 12:24 AM <DIR> include
11/05/2023 12:24 AM <DIR> jmods
11/05/2023 12:24 AM <DIR> legal
11/05/2023 12:24 AM <DIR> lib
11/05/2023 12:20 AM 160 README.html
11/05/2023 12:20 AM 1,344 release
2 File(s) 1,504 bytes
8 Dir(s) 416,704,659,456 bytes free

In each case, we’ll get out a directory listing. Notice a directory inside of our JAVA_HOME folder called bin. Bin is short for 'binaries' and it's where all these little programs are. So what we want to do is make sure this bin directory is somehow a part of our PATH environment variable.

To update the PATH variable on macOS, we open up our .zshrc file that we've been editing, and check to see if any PATH variable is being exported in it. If so, we can just modify that line. If not, we can create a new line that starts with:

export PATH=$PATH

The first thing we do is set PATH to itself. Why do we set PATH to itself? Well, PATH may have some values in it already set from some previous shell startup script, and we don’t want to clobber those. So we first make sure that we’re keeping any existing values. Then, we add the directory we want to the PATH, by changing the line so that it looks like this:

export PATH=$PATH:$JAVA_HOME/bin

Now we are using two environment variables to define PATH — any previous PATH value, and our new JAVA_HOME variable. Since we’re using JAVA_HOME, we need to write this PATH export line after we define the JAVA_HOME variable. And all we are doing is telling the PATH that we want whatever is inside the bin dir inside JAVA_HOME to be on the path. We can add as many directories as we want to the PATH, by separating them with colons. This is how we build up our list of directories in our path.

On Windows, we head to the Environment variable editor as before. In either your user or system variables, you should see an existing variable called Path. Click to edit it.

The editor for the Path variable is special - it shows us a list of paths, and we can add to this list by clicking "New".

So click ”New” and add %JAVA_HOME%\bin, then save it to the list.

Notice that again we are using another environment variable to help define the Java binary directory we want to use in our path. This means that if we change the value of JAVA_HOME down the line, say because we downloaded a new version of Java, we don't also need to update our Path.

Some older versions of Windows have the Path variable as one long string, in which case the value works just the same as it does on Mac, just separate each directory with semicolons ; instead of colons : (and make sure to use the Windows format for variables and paths of course).

We have now set our Java home environment variable and our path variable in such a way that we should have access to the Java binary programs from our shell without needing to know where they are anymore. So open up a new terminal or command prompt, and check if this is the case by trying to run the java command. If it works, you should get a bunch of help output from java, as shown below. And note that whether you are on Mac or Windows, you can run the same Java command.

% java
Usage: java [options] <mainclass> [args...]
(to execute a class)
or java [options] -jar <jarfile> [args...]
(to execute a jar file)
or java [options] -m <module>[/<mainclass>] [args...]
java [options] --module <module>[/<mainclass>] [args...]
(to execute the main class in a module)
or java [options] <sourcefile> [args]
(to execute a single source-file program)
...
‘java’ command output on macOS
‘java’ command output on Windows

If it doesn’t work, if you didn’t get output similar to this, then go back through these steps or check the Java installation documentation or usage for your shell to make sure that you’ve set up your environment correctly. Remember we can always echo environment variables to make sure they have the content we expect. For example, we can echo out the two variables we added:

% echo $JAVA_HOME
/usr/local/Cellar/openjdk@11/11.0.21/libexec/openjdk.jdk/Contents/Home
% echo $PATH
/Library/Frameworks/Python.framework/Versions/3.11/bin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/Library/Java/JavaVirtualMachines/openjdk-11.jdk/Contents/Home/bin:/usr/local/opt:/usr/local/Cellar/openjdk@11/11.0.21/libexec/openjdk.jdk/Contents/Home/bin:/Users/lanabegunova/bin:/Users/lanabegunova/Library/Android/sdk/emulator:/Users/lanabegunova/Library/Android/sdk/platform-tools:/Users/lanabegunova/Library/Android/sdk/tools:/Users/lanabegunova/Library/Android/sdk/tools/bin

And on Windows, make sure to use the percent % signs of course.

% echo %JAVA_HOME%
C:\Program Files\Java\jdk-11.0.21
% echo %PATH%
C:\oraclexe\app\oracle\product\11.2.0\server\bin;C:\Users\begun\AppData\Local\Programs\Python\Python311\Scripts;C:\Users\begun\AppData\Local\Programs\Python\Python311;C:\Program Files (x86)\Common Files\Oracle\Java\javapathC:\Program Files\Java\jdk-11.0.21\bin;C:\opt\apache-maven-3.8.1\bin;C:\Users\begun\AppData\Local\Android\Sdk\tools\bin;C:\Users\begun\AppData\Local\Android\Sdk\tools;C:\Users\begun\AppData\Local\Android\Sdk\platform-tools;C:\Program Files\SourceGear\Common\DiffMerge\;C:\Program Files\Git\cmd;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;C:\Program Files\nodejs\;C:\ProgramData\chocolatey\bin;C:\Program Files\Java\jdk-11.0.21\bin;C:\Users\begun\AppData\Local\Programs\Python\Python311\Scripts\;C:\Users\begun\AppData\Local\Programs\Python\Python311\;C:\Users\begun\AppData\Local\Programs\Python\Python310\Scripts\;C:\Users\begun\AppData\Local\Programs\Python\Python310\;C:\Program Files\Java\jdk1.8.0_271\bin;C:\Users\begun\AppData\Local\Programs\Microsoft VS Code\bin;C:\Users\begun\AppData\Local\Microsoft\WindowsApps;C:\Users\begun\AppData\Roaming\npm;C:\Users\begun\AppData\Local\GitHubDesktop\bin;

So that’s it for setting up Java and our Java environment.

I welcome any comments and contributions to the subject. Connect with me on LinkedIn, X or GitHub.

--

--

Lana Begunova

I am a QA Automation Engineer passionate about discovering new technologies and learning from it. The processes that connect people and tech spark my curiosity.