vscode-java icon indicating copy to clipboard operation
vscode-java copied to clipboard

Fall back to java.jdt.ls.java.home if embedded JRE fails

Open Magendanz opened this issue 3 years ago • 17 comments

When deploying VSCode to an AP Computer Science lab where the students don't have admin privileges, attempts to enable the latest Extension Pack for Java (which includes the “Language Support for Java(TM) by Red Hat” extension) fail reporting “Couldn’t start client Language Support for Java” whenever they open a Java project.

Environment
  • Operating System: Windows 10
  • JDK version: Various (tried latest Microsoft OpenJDK 11 & 17 as well as those from Adoptium's Teemurin)
  • Visual Studio Code version: 1.64.0
  • Java extension version: v 1.1.0 through v1.3.0
Steps To Reproduce
  1. Install latest VSCode and JDK (with JAVA_HOME set correctly)
  2. Create a new Java class
Current Result

Reports “Couldn’t start client Language Support for Java” when trying to run or debug the Java code.

Expected Result

Should work like it does for users with admin privileges (or how it did for v1.0.0).

Additional Information

Works fine for users with admin privileges or if we roll the students back to v1.0.0 of this extension. Typing java -version in terminal returns correct OpenJDK version.

Magendanz avatar Feb 08 '22 15:02 Magendanz

I just tested with a clean VM but I could not reproduce it with v1.3.0.

Detailed client logs can be found when you run command Java: Open Java Extension Log. Can you attach it?

Eskibear avatar Feb 09 '22 08:02 Eskibear

This command results in the following alert dialog: "Command 'Open Java Extensions Log' resulted in an error. Command 'java.open.clientLog' not found."

Magendanz avatar Feb 09 '22 15:02 Magendanz

However, I was able to grab this log by downgrading to v.1.0.0 first and then upgrading to v1.3.0. client.log.2022-02-09.txt

Magendanz avatar Feb 09 '22 15:02 Magendanz

{
  message: 'Error: spawn UNKNOWN\n' +
    '\tat ChildProcess.spawn (internal/child_process.js:403:11)\n' +
    '\tat Object.spawn (child_process.js:570:9)\n' +
    '\tat c:\\Users\\032\\.vscode\\extensions\\redhat.java-1.3.0\\dist\\extension.js:2:1041140',
  level: 'info',
  timestamp: '2022-02-09 07:36:42.683'
}

This error was thrown by below line.

https://github.com/microsoft/vscode-languageserver-node/blob/94a47841cd3c4679a5facae305dfe92734eeffb3/client/src/node/main.ts#L435

Looks like the command to launch server was correctly passed, it's strange why this error occurred (and only for non-admin users).

Eskibear avatar Feb 10 '22 02:02 Eskibear

Similar stacktraces found on https://github.com/NightrainsRbx/RobloxLsp/issues/131 & https://github.com/nodejs/node-v0.x-archive/issues/6797 . Both are on Windows. Is there any chance some configuration on those machines prevent regular users from spawning a Java process ? Still not sure what would have changed in vscode-java to result in this behaviour though.

We did update ts-loader for 1.1.0.

rgrunber avatar Feb 10 '22 02:02 rgrunber

So, it appears that the Red Hat Java extension was getting blocked by AppLocker. We've worked around it by updating AppLocker policies to allow any executable in this path: c:\users*.vscode\extensions\redhat.java*

However, this workaround has only been approved for our lab machines. If the school district allows this group policy change onto student laptops, we would eventually find students putting their own executables (games, malware, unapproved software, etc.) off c:\users*.vscode\extensions\redhat.java*. and running them. (Even students that don’t have VSCode would be able to do that when their friends find the loophole and pass it along.) The policy change has only been approved for the labs because it's a supervised environment that can be a little looser.

Can you help me understand how the extension's behavior changed after v1.0.0? We really need to allow our AP CS students to use VSCode on their student laptops from home or during study halls, but we also need to make it work without adding loopholes for students to run their own executables. Was that loophole still there with the 1.0.0 ts-loader but AppLocker just wasn't catching it?

Magendanz avatar Feb 16 '22 04:02 Magendanz

@Magendanz You can try to disable the embedded JRE. See https://github.com/redhat-developer/vscode-java/issues/2276#issuecomment-1015035058

snjeza avatar Feb 16 '22 04:02 snjeza

Hey @Magendanz, since version 1.2.0, we embedded a JRE to start the Java extension itself, which is installed in a location like c:\users*.vscode\extensions\redhat.java*. If this directory is not allowed by the school environment, you can configure a different JDK for Java tools using the VS Code user setting "java.jdt.ls.java.home".

testforstephen avatar Feb 16 '22 07:02 testforstephen

If we specify JAVA_HOME, shouldn't the extension use that instead of the embedded JRE?

Frankly, the easiest workaround for us at this point is to simply roll back to v1.0.0 of the RedHat extension. It's not even clear to me how I would roll out a java.jdt.ls.java.home user setting for a lab where I'm doing a system-level install.

Magendanz avatar Mar 01 '22 15:03 Magendanz

If we specify JAVA_HOME, shouldn't the extension use that instead of the embedded JRE?

Then JAVA_HOME will be picked as default JDK to compile and run your project, but embedded JRE is still used to launch this extension (actually JDT Language Server) to provide language features. That's by design, to reduce the confusion caused by JDK requirements. There is case when you do want to launch language server with your own JDK in case embedded JRE is not working, and java.jdt.ls.java.home is designed for that.

how I would roll out a java.jdt.ls.java.home user setting for a lab where I'm doing a system-level install

AFAIK there's not system-level settings file. You'll have to specify this setting for each users in their user settings.

Workaround for your case

If all you want is a simple way (e.g. via JAVA_HOME env) to provision the machines and provide out-of-box for multiple users of the lab machine, you can install "universal version" of vscode-java extension, which doesn't have any JRE embedded. See "Universal Version" section in JDK requirements. You can download and install .visx by your own, from open-vsx for example.

Eskibear avatar Mar 01 '22 16:03 Eskibear

It's not even clear to me how I would roll out a java.jdt.ls.java.home user setting for a lab where I'm doing a system-level install.

On Windows, usually VS Code user settings are stored at C:\Users\*\AppData\Roaming\Code\User\settings.json. When doing a system-level install, copy a modified settings.json with "java.jdt.ls.java.home". Does that help?

testforstephen avatar Mar 02 '22 01:03 testforstephen

On Windows, usually VS Code user settings are stored at C:\Users*\AppData\Roaming\Code\User\settings.json. When doing a system-level install, copy a modified settings.json with "java.jdt.ls.java.home". Does that help?

The problem is that at the time of deployment the user profile directories haven't even been created yet. We have to set these lab machines up so that any student (domain member) can just log in and use VS Code.

We're looking into the "universal version" of this extension, which seems promising, but it's not clear where we do a system-level install of .vsix files. Ideally, we'd like to create a system install version of the Coding Pack for Java with all extensions in the Extension Pack for Java preinstalled.

Magendanz avatar Mar 02 '22 01:03 Magendanz

If we specify JAVA_HOME, shouldn't the extension use that instead of the embedded JRE?

Then JAVA_HOME will be picked as default JDK to compile and run your project, but embedded JRE is still used to launch this extension (actually JDT Language Server) to provide language features. That's by design, to reduce the confusion caused by JDK requirements.

How about if the extension fails to launch the embedded JRE that it just tries the alternative paths (java.jdt.ls.java.home, java.home, JDK_HOME, JAVA_HOME, etc.) until it finds one that works...just like the Universal Version does?

Magendanz avatar Mar 02 '22 01:03 Magendanz

@Eskibear , we can't yet recover from failed launch of embedded JRE due to https://github.com/microsoft/vscode-languageserver-node/issues/688 right ? If that ever gets resolved, do you see us automatically attempting to use java.jdt.ls.java.home ? If not we can close this since at least there is a workaround. Otherwise, we can keep it open.

rgrunber avatar May 28 '22 00:05 rgrunber

we can't yet recover from failed launch of embedded JRE due to https://github.com/microsoft/vscode-languageserver-node/issues/688 right ?

For the moment, language client doesn't report exit code of server. So we cannot accurately take followup actions based on exit code. AFAIK, technically if we want to restart server with a different executable, maybe ClientOption.ErrorHandler can do the trick.

If that ever gets resolved, do you see us automatically attempting to use java.jdt.ls.java.home ?

No. java.jdt.ls.java.home has higher priority than embedded JRE. Falling back to attempt with env.JAVA_HOME would be possible. But I don't like that way that messes all the concepts up with implicit dependency on env.JAVA_HOME. I think the a solution to this issue can be: universal version of java extension + pre-defined user settings with java.jdt.ls.java.home.

Eskibear avatar Jun 02 '22 05:06 Eskibear

Renamed this so at least we can track it. Probably lower priority given a solution exists, but at least we can revisit in the future.

rgrunber avatar Jun 02 '22 14:06 rgrunber

Not this exact issue, but we're looking at the reverse of this (java.jdt.ls.java.home doesn't meet the requirements, so fall back to the embedded JRE) on https://github.com/redhat-developer/vscode-java/pull/2512 .

rgrunber avatar Jun 15 '22 16:06 rgrunber