tohuwabohu In technology, chaos reigns supreme.

Java Projects in WSL and IntelliJ: The Pitfalls


From a Java developer perspective, I most certainly appreciate the usability Windows Subsystem for Linux (WSL) offers. It’s much easier to set up and use for me than dual boot, the maintenance of multiple Java runtime environments and switching between them is easier than on Windows and using the bash does not feel as clunky as the PowerShell.

But I have to admit, some things just don’t work out of the box, and I was surprised when maybe one of the most basic use cases in today’s software engineering made me spend a big chunk of my time: Setting up a working Java workspace with my year-long IDE of choice, IntelliJ IDEA. While installing and maintaining different Java versions is pretty easy thanks to Ubuntu, getting some code to compile and being able to debug definitely was not. The jetbrains help page does have an own section for WSL setup , so I won’t explain the whole process here. Over the next few paragraphs I describe the pitfalls I encountered that were not mentioned on the help page and how I finally solved them.

Directory ownership

I stumbled upon this problem when trying to help someone with his Java task and therefore wanted to import his project into my workspace. After doing so, the IDE showed me a strange access error when I tried to run the application. It turned out that the project directory created in IntelliJ’s compile-server folder had root ownership. To elobarate further, let’s play this through with an example.

First, set up a new project with IntelliJ located in your WSL installation.

Set up a new project with IntelliJ located in your WSL installation.
Set up a new project with IntelliJ located in your WSL installation.

Second, just create a Hello World example to your liking. A simple main class will suffice.

package io.tohuwabohu.test;

public class Test {
    public static void main(String[] args) {
        System.out.println("Welp");
    }
}

Then try to execute the main method with your IDE. There is a chance that you will see an error similar to the one below.

Internal error (java.nio.file.AccessDeniedException): /home/steff-man/.cache/JetBrains/IntelliJIdea2021.3/compile-server/test-project_71ab9d78/timestamps
java.nio.file.AccessDeniedException: /home/steff-man/.cache/JetBrains/IntelliJIdea2021.3/compile-server/test-project_71ab9d78/timestamps
	at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:90)
	at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:106)
	at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111)
	at java.base/sun.nio.fs.UnixFileSystemProvider.createDirectory(UnixFileSystemProvider.java:398)
	at java.base/java.nio.file.Files.createDirectory(Files.java:700)
	at java.base/java.nio.file.Files.createAndCheckIsDirectory(Files.java:807)
	at java.base/java.nio.file.Files.createDirectories(Files.java:793)
	at com.intellij.util.io.ResizeableMappedFile.ensureParentDirectoryExists(ResizeableMappedFile.java:181)
	at com.intellij.util.io.ResizeableMappedFile.<init>(ResizeableMappedFile.java:67)
	at com.intellij.util.io.PersistentBTreeEnumerator.<init>(PersistentBTreeEnumerator.java:93)
	at com.intellij.util.io.PersistentEnumerator.createDefaultEnumerator(PersistentEnumerator.java:66)
	at com.intellij.util.io.PersistentMapImpl.<init>(PersistentMapImpl.java:136)
	at com.intellij.util.io.PersistentMapBuilder.buildImplementation(PersistentMapBuilder.java:62)
	at com.intellij.util.io.PersistentMapBuilder.build(PersistentMapBuilder.java:44)
	at com.intellij.util.io.PersistentHashMap.<init>(PersistentHashMap.java:39)
	at com.intellij.util.io.PersistentHashMap.<init>(PersistentHashMap.java:54)
	at org.jetbrains.jps.incremental.storage.AbstractStateStorage.createMap(AbstractStateStorage.java:116)
	at org.jetbrains.jps.incremental.storage.AbstractStateStorage.<init>(AbstractStateStorage.java:29)
	at org.jetbrains.jps.incremental.storage.FileTimestampStorage.<init>(FileTimestampStorage.java:27)
	at org.jetbrains.jps.incremental.storage.ProjectStamps.<init>(ProjectStamps.java:41)
	at org.jetbrains.jps.cmdline.BuildRunner.load(BuildRunner.java:97)
	at org.jetbrains.jps.cmdline.BuildSession.runBuild(BuildSession.java:311)
	at org.jetbrains.jps.cmdline.BuildSession.run(BuildSession.java:162)
	at org.jetbrains.jps.cmdline.BuildMain$MyMessageHandler.lambda$channelRead0$0(BuildMain.java:218)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
	at java.base/java.lang.Thread.run(Thread.java:833)
Please perform full project rebuild (Build | Rebuild Project)

If you see this, verify the assumption. Locate the compile-server folder via the command line. Usually it’s in your home directory in the hidden .cache folder.

steff-man@DESKTOP-62DJI5M:~/.cache/JetBrains/IntelliJIdea2021.3$ ls -l compile-server/
total 12
drwxr-xr-x 3 steff-man steff-man 4096 Jun  5 15:12 jps-IU-213.5744.223
drwxr-xr-x 9 steff-man steff-man 4096 Jun  5 15:12 streams-test_f9925fb6
drwxr-xr-x 4 root      root      4096 Jun  5 15:37 test-project_71ab9d78

You can fix this with a chown command to set the ownership back to the user you’d expect to have permission.

steff-man@DESKTOP-62DJI5M:~/.cache/JetBrains/IntelliJIdea2021.3$ sudo chown steff-man compile-server/test-project_71ab9d78
steff-man@DESKTOP-62DJI5M:~/.cache/JetBrains/IntelliJIdea2021.3$ ls -l
total 12
drwxr-xr-x 3 steff-man steff-man 4096 Jun  5 15:12 jps-IU-213.5744.223
drwxr-xr-x 9 steff-man steff-man 4096 Jun  5 15:12 streams-test_f9925fb6
drwxr-xr-x 4 steff-man steff-man 4096 Jun  5 15:37 test-project_71ab9d78

After that, code execution should work as expected.

Strangely enough, this error does not occur regularly, at least not in my case. I recommend setting up the project directory in the WSL through a mkdir command instead of the IDE. Albeit in my case, the project directory itself did not have root ownership, but the compile-server folder did. I completely removed the folder structure underneath and have not had any access errors since.

Debugger connection

After finally solving the compilation issues I pushed my luck and tried debugging. I set up a breakpoint in the rudimentary example believing it would work, but it did not. The process refused any attempt for me to connect. Usually for local workspaces this just works out of the box with no changes needed.

Naturally, I looked into the settings screen for clues.

Seems like that the wrong port was set here. At least I thought so because by changing this default value to the suggested port 12345, I doomed myself for the next few hours. Do not change this value. Leave it as it is. For the curious: If you decide to change this setting, you might encounter a different error message from the debugger.

And googling this error won’t help much because there are many issues related to docker, OpenShift and many other systems but those are completely unrelated to the WSL error and exhausting to dig through. I dug through and found someone that finally made the whole thing work.

I mentioned the WSL help page in the introduction and how I won’t explain the whole process here. However, there is a part where you need to change firewall settings and execute the following commands in the PowerShell.

New-NetFirewallRule -DisplayName "WSL" -Direction Inbound  -InterfaceAlias "vEthernet (WSL)"  -Action Allow
Get-NetFirewallRule | where DisplayName -ILike "IntelliJ IDEA*"

After doing so, please also check the Windows firewall settings and verify that your IntelliJ installation as access granted for both private and public networks.

Then look if the wsl.obtain.windows.host.ip.alternatively flag is set in the IntelliJ Registry. Open the registry with the Access-shortcut ctrl+shift+A and type “Registry” in the box. You find the flag by typing its name.

And finally, adjust the Run/Debug configuration for your project. Add -Djava.net.preferIPv4Stack=trueto the VM options.

After that, the IDE should be able to connect to the debug process.

So, after a few exhausting hours I finally got a working Java workspace on WSL with IntelliJ IDEA. Sadly, there is no global solution for the debugger, so at least the -Djava.net.preferIPv4Stack=true setting needs to be additionally set as VM argument for each configuration. I have yet to try a bigger project including maven, gradle and so on, but I hope that this summary may help somebody in the future.

Tagged as: intellij java wsl