在Windows中切换不同的JDK版本

33

我正在处理几个项目,其中一些使用了不同版本的JDK。在各种JDK版本之间切换并不方便。因此,我想知道是否有简单的方法来更改它?

我找到了两种解决方法,但都没有成功。

第一个解决方案是创建像这样的批处理文件:

@echo off
echo Setting JAVA_HOME
set JAVA_HOME=C:\Program Files\Java\jdk1.7.0_72
echo setting PATH
set PATH=C:\Program Files\Java\jdk1.7.0_72\bin;%PATH%
echo Display java version
java -version
pause

运行这个批处理之后,我看到了正确版本的Java。但是当我关闭这个CMD并打开一个新的CMD,输入"java -version"时,它说我仍然有1.8.0_25的版本。所以它不起作用。

我找到的第二种解决方案是来自这个网站的应用程序。但它也不起作用。与第一种解决方案的效果相同。

有什么想法吗?因为通过Win+Pause->高级系统设置->环境变量->编辑这些变量来更改JAVA_HOME和PAHT,是一种可怕的方法...


使用批处理文件设置路径,并在批处理文件中执行Java。 - brb tea
1
正如您所看到的,这两个变量都在批处理文件中设置。但我不知道如何在此文件中执行Java。我在另一个页面上找到了这个解决方案,但我不知道如何编写批处理文件。 - Lui
7个回答

44
set命令只对当前终端有效。要永久设置系统或用户环境变量,您可以使用setx命令。
您可以像这样为当前用户设置变量:
setx JAVA_HOME "C:\Program Files\Java\jdk1.7.0_72"

你还可以通过以管理员身份运行终端,并使用相同的命令加上 /m 选项来在整个系统范围内设置变量。注意:终端必须以管理员身份运行。
setx JAVA_HOME "C:\Program Files\Java\jdk1.7.0_72" /m

变量将在所有新的终端会话中可用,但不包括当前会话。如果您还想在同一个会话中使用该路径,您需要同时使用setsetx
如果您只需将%JAVA_HOME%放入PATH中一次,而不是完整的JDK路径,就可以避免操作PATH变量。如果您更改了JAVA_HOMEPATH也将被更新。

除了繁琐的Windows环境变量设置之外,还有一些环境变量编辑器可作为替代方案。请查看 Super User 上的 "在Windows 7中是否有方便的方法来编辑路径?"。


2
嗯,有些问题...我按照你说的做了,它添加了这些变量,但是对于用户来说...当我打开新终端时,仍然会得到我想要的不同JDK的信息... - Lui
1
缺少 /m 选项,我已经更新了答案。 - kapex
@OddDev如果您想永久更改PATH,您也需要使用“setx”。但是,它会在每次运行脚本时都添加Java路径,因此最好删除该行,并仅将“%JAVA_HOME%”添加到PATH中一次。 - kapex
1
终端或应用程序需要重新启动以考虑由更新的JAVA_HOME引起的PATH更改。或者请参阅https://dev59.com/-XVC5IYBdhLWcg3w1Exq。 - Konstantin Spirin
1
@ACV 如果您没有权限设置环境变量,您将会收到该错误。您需要以管理员身份运行 cmd - kapex
显示剩余3条评论

14

如果有人想在每个新的命令窗口中频繁切换,则可以使用以下方法。

命令提示符版本:

使用下面的代码创建批处理文件。您可以使用if和else块添加任意数量的版本。

@echo off
if "%~1" == "11" (
   set "JAVA_HOME=C:\Software\openjdk-11+28_windows-x64_bin\jdk-11"
) else (
   set "JAVA_HOME=C:\Program Files\Java\jdk1.8.0_151"
)
set "Path=%JAVA_HOME%\bin;%Path%"
java -version

将此批处理文件保存为SJV.bat,并将此文件位置添加到计算机的Path环境变量中。现在SJV将作为“切换Java版本”的命令。

现在打开新的命令窗口,只需键入SJV 11,它会切换到Java 11。键入SJV 8,它会切换到Java 8。

PowerShell版本

使用以下代码创建powershell(ps1)文件。您可以使用if和else块添加n个版本。

If($args[0] -eq "11")
{
    $env:JAVA_HOME = 'C:\Software\openjdk-11+28_windows-x64_bin\jdk-11'
}else{
    $env:JAVA_HOME = 'C:\Program Files\Java\jdk1.8.0_151'
}
$env:Path = $env:JAVA_HOME+'\bin;'+$env:Path
java -version

将此脚本文件保存为SJV.ps1,并将该文件位置添加到计算机的Path环境变量中。现在,SJV将充当“切换Java版本”的命令。

现在打开新的PowerShell窗口,只需输入SJV 11即可切换到Java 11。 输入SJV 8SJV将切换到Java 8。

我希望这能帮助需要经常更改Java版本的人。


1
注意:此代码在命令行上有效,但在PowerShell上无效。 - Jatin
@Jatin 我已经更新了答案,并附上了 PowerShell 脚本。 - Prakash Boda
当我打开其他窗口并输入"java -version"时,我得到的是旧版本。 - BeatrizGomes
在每个窗口中,您需要首先使用所需的Java版本(如SJV 8或SJV 11)运行SJV命令。然后它将提供正确的版本。 - Prakash Boda

10
  1. Open Environment Variables editor (File Explorer > right click on This PC > Properties > Advanced system settings > Environment Variables...)
  2. Find Path variable in System variables list > press Edit > put %JAVA_HOME%bin; at first position. This is required because Java installer adds C:\Program Files (x86)\Common Files\Oracle\Java\javapath to the PATH which references to the latest Java version installed. enter image description here
  3. Now you can switch between Java version using setx command (should be run under administrative permissions):

    setx /m JAVA_HOME "c:\Program Files\Java\jdk-10.0.1\
    

    (note: there is no double quote at the end of the line and should not be or you'll get c:\Program Files\Java\jdk-10.0.1\" in your JAVA_HOME variable and it breaks your PATH variable)

通过系统变量的解决方案(以及管理员权限)更加健壮,因为它将期望的Java路径放在最终PATH变量的开头。


1
如果您的路径少于1024个字符,可以执行(以管理员身份运行)此脚本:
@echo off 
set "JAVA5_FOLDER=C:\Java\jdk1.5.0_22"
set "JAVA6_FOLDER=C:\Java\jdk1.6.0_45"
set "JAVA7_FOLDER=C:\Java\jdk1.7.0_80"
set "JAVA8_FOLDER=C:\Java\jdk1.8.0_121"
set "JAVA9_FOLDER=C:\Java\jdk-10.0.1"
set "CLEAR_FOLDER=C:\xxxxxx"

(echo "%PATH%" & echo.) | findstr /O . | more +1 | (set /P RESULT= & call exit /B %%RESULT%%)
set /A STRLENGTH=%ERRORLEVEL%
echo path length = %STRLENGTH%
if %STRLENGTH% GTR 1024  goto byebye 

echo Old Path: %PATH%
echo =================== 
echo Choose new Java Version:
echo [5] JDK5
echo [6] JDK6 
echo [7] JDK7
echo [8] JDK8
echo [9] JDK10
echo [x] Exit

:choice 
SET /P C=[5,6,7,8,9,x]? 
for %%? in (5) do if /I "%C%"=="%%?" goto JDK_L5 
for %%? in (6) do if /I "%C%"=="%%?" goto JDK_L6
for %%? in (7) do if /I "%C%"=="%%?" goto JDK_L7 
for %%? in (8) do if /I "%C%"=="%%?" goto JDK_L8 
for %%? in (9) do if /I "%C%"=="%%?" goto JDK_L9
for %%? in (x) do if /I "%C%"=="%%?" goto byebye
goto choice 

@echo on
:JDK_L5  
set "NEW_PATH=%JAVA5_FOLDER%"
goto setPath

:JDK_L6  
@echo off 
set "NEW_PATH=%JAVA6_FOLDER%"
goto setPath

:JDK_L7  
@echo off 
set "NEW_PATH=%JAVA7_FOLDER%"
goto setPath

:JDK_L8  
@echo off 
set "NEW_PATH=%JAVA8_FOLDER%"
goto setPath

:JDK_L9  
@echo off 
set NEW_PATH = %JAVA9_FOLDER%

:setPath
Call Set "PATH=%%PATH:%JAVA5_FOLDER%=%CLEAR_FOLDER%%%"
Call Set "PATH=%%PATH:%JAVA6_FOLDER%=%CLEAR_FOLDER%%%"
Call Set "PATH=%%PATH:%JAVA7_FOLDER%=%CLEAR_FOLDER%%%"
Call Set "PATH=%%PATH:%JAVA8_FOLDER%=%CLEAR_FOLDER%%%"
Call Set "PATH=%%PATH:%JAVA9_FOLDER%=%CLEAR_FOLDER%%%"
rem echo Interim Path: %PATH%
Call Set "PATH=%%PATH:%CLEAR_FOLDER%=%NEW_PATH%%%" 

setx PATH "%PATH%" /M

call set "JAVA_HOME=%NEW_PATH%"
setx JAVA_HOME %JAVA_HOME% 

echo New Path: %PATH%
:byebye
echo
java -version
pause

如果超过1024个字符,尝试删除一些不必要的路径,或者可以根据https://superuser.com/questions/387619/overcoming-the-1024-character-limit-with-setx中的一些输入修改这些脚本。

1

在此答案(https://dev59.com/o18d5IYBdhLWcg3wTAl-#64459399)的基础上进行补充。

我通过 UI 手动创建了 Java11Java17Java8 的环境变量。要跨 Java 版本更改:

从 PowerShell (PJV.ps1) 中执行:

if($args[0] -eq "11") {
   $Env:JAVA_HOME="$ENV:JAVA11"
   $Env:Path="$Env:JAVA_HOME\bin;$Env:Path"
} elseif($args[0] -eq "17") {
   $Env:JAVA_HOME="$ENV:JAVA17"
   $Env:Path="$Env:JAVA_HOME\bin;$Env:Path"
} elseif($args[0] -eq "8") {
   $Env:JAVA_HOME="$ENV:JAVA8"
   $Env:Path="$Env:JAVA_HOME\bin;$Env:Path"
}
set "Path=%JAVA_HOME%\bin;%Path%"
java -version

从命令行(JV.bat):

@echo off
if "%~1" == "11" (
   set "JAVA_HOME=%JAVA11%"
   setx JAVA_HOME "%JAVA11%"
) else if "%~1" == "17" (
   set "JAVA_HOME=%JAVA17%"
   setx JAVA_HOME "%JAVA17%"
) else (
   set "JAVA_HOME=%JAVA8%"
   setx JAVA_HOME "%JAVA8%"
)
set "Path=%JAVA_HOME%\bin;%Path%"
java -version

最后,这两个文件都在同一个文件夹中。并且该文件夹路径已添加到我的系统PATH中。

enter image description here


0

在 PowerShell 启动时加载下面提到的 PowerShell 脚本,或使用 New-Item $profile -Type File -Force 生成文件。

这将在此处创建一个文件:C:\Users\{user_name}\Documents\WindowsPowerShell\Microsoft.PowerShell_profile

现在将以下内容复制粘贴到此文件中,以便每次启动 PowerShell 时都会加载它:

为所需的所有 Java 版本设置不同的变量。

  1. Java_8_home -> 指向本地 Java 8 位置
  2. Java_11_home -> 指向本地 Java 11 位置
  3. Java_17_home -> 指向本地 Java 17 位置
  4. Java_Home -> 这指向您想要使用的 Java 版本

在 PowerShell 中运行以下命令以将版本更新为 8:update_java_version 8 $True

要更新执行策略以允许在 PowerShell 启动时加载脚本,请使用以下命令:Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Unrestricted -Force

`

function update_java_version($version, [bool] $everywhere)
{
    switch ($version)
    {
        8 {
            $java_value = (Get-Item Env:Java_8_home).value
            $Env:Java_Home = $java_value
            refresh-path
            break
        }
        11 {
            $java_value = (Get-Item Env:Java_11_home).value
            $Env:Java_Home = $java_value
            refresh-path
            break
        }
        17 {
            $java_value = (Get-Item Env:Java_17_home).value
            $Env:Java_Home = $java_value
            refresh-path
            break
        }
        default {
            throw "No matching java version found for `$version`: $version"
        }
    }
    if ($everywhere)
    {
        [System.Environment]::SetEnvironmentVariable("Java_Home", $java_value, "User")
    }
}

function refresh-path
{
    $env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") +
            ";" +
            [System.Environment]::GetEnvironmentVariable("Path", "User")
}

0

运行此BAT文件可以方便地更改Java版本。

优点:

  1. 它不会修改PATH系统环境变量。
  2. 唯一需要维护的是关系数组(可以方便地构建为稀疏数组),该数组在脚本开头保存版本号和路径。

前提条件:

必须将以下条目%JAVA_HOME%\bin 附加PATH环境变量中。

@echo off
@cls
@title Switch Java Version
setlocal EnableExtensions DisableDelayedExpansion

:: This bat file Switches the Java Version using the JAVA_HOME variable.
:: This script does NOT modify the PATH system environment variable.
:: Precondition: The following entry "%JAVA_HOME%\bin" has to be appended to the PATH environment variable.
::  Script Name: SwitchJavaVersion | Version 1 | 2021/11/04

rem Add items to vector as follows:
rem   AvailableVersions["Java Major Version Number"]="Java Absolute Path"
set AvailableVersions[8]="D:\Program Files\Java\jdk8u252-b09"
set AvailableVersions[17]="D:\Program Files\Java\jdk-17.0.1"

call :PrintJavaVersion
call :PrintAvailableVersions
call :GetJavaVersion
call :SetJavaVersion
call :ResetLocalPath
if %errorlevel% neq 0 exit /b %errorlevel%
call :PrintJavaVersion

pause
endlocal
exit /b


rem Print available versions.
:PrintAvailableVersions
    echo Available Java Versions:
    for /f "tokens=2 delims=[]" %%I in ('set AvailableVersions[') do echo ^> %%I
    exit /b

rem Get version from user input or command-line arguments.
:GetJavaVersion
    set "JavaVersion="
    if "%~1"=="" (
        set /p JavaVersion="Type the major java version number you want to switch to: "
    ) else (
        set /a JavaVersion="%~1"
    )
    exit /b


rem Update JAVA_HOME user variable with hardcoded paths.
:SetJavaVersion
    set JavaPath=
    for /f "tokens=2 delims=[]" %%I in ('set AvailableVersions[') do (
        if "%%I" == "%JavaVersion%" (
            setlocal EnableDelayedExpansion
            set JavaPath=!AvailableVersions[%%I]!
            setlocal EnableExtensions DisableDelayedExpansion
        )
    )

    if not defined JavaPath (
        echo "Specified version NOT found: Default settings applied."
        for /f "tokens=2 delims==" %%I in ('set AvailableVersions[') do (
            set JavaPath=%%I
            goto exitForJavaPath
        )
        
    )
    :exitForJavaPath

    rem remove quotes from path
    set JavaPath=%JavaPath:"=%
    set "JAVA_HOME=%JavaPath%"
    setx JAVA_HOME "%JAVA_HOME%"
    
    rem setlocal statement was run 2 times previously inside the for loop; therefore, the endlocal statement must be executed 2 times to close those nested local scopes.

    
    rem below endlocal statement will close local scope set by previous "setlocal EnableExtensions DisableDelayedExpansion" statement
    endlocal & set "JavaPath=%JavaPath%"
    rem JAVA_HOME's value rolls back due to endlocal statement so the appropriate value has to be reassigned
    set "JAVA_HOME=%JavaPath%"
    rem below endlocal statement will close local scope set by previous "setlocal EnableDelayedExpansion" statement
    endlocal & set "JavaPath=%JavaPath%"
    rem JAVA_HOME's value rolls back due to endlocal statement so the appropriate value has to be reassigned
    set "JAVA_HOME=%JavaPath%"
    
    exit /b


rem Get User and System Path variable's definition from Registry,
rem    evaluate the definitions with the new values and reset
rem    the local path variable so newly set java version
rem    is properly displayed.
:ResetLocalPath
    set "PathValue="
    for /F "skip=2 tokens=1,2,*" %%I in ('%SystemRoot%\System32\reg.exe QUERY "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /V Path') do if /I "%%I" == "Path" if not "%%~K" == "" if "%%J" == "REG_SZ" (set "PathValue=%%~K") else if "%%J" == "REG_EXPAND_SZ" call set "PathValue=%%~K"

    if not defined PathValue goto pathError

    set "UserPathValue="
    for /F "skip=2 tokens=1,2,*" %%I in ('%SystemRoot%\System32\reg.exe QUERY "HKCU\Environment" /V Path') do if /I "%%I" == "Path" if not "%%~K" == "" if "%%J" == "REG_SZ" (set "UserPathValue=%%~K") else if "%%J" == "REG_EXPAND_SZ" call set "UserPathValue=%%~K"

    if not defined UserPathValue goto pathError
    
    call set "Path=%PathValue%;%UserPathValue%"

    echo Path variable reset:
    echo PATH=%Path%  
    echo.
    exit /b


rem Display the Java version.
:PrintJavaVersion
    echo Current Java Version:
    java -version
    echo.
    exit /b


rem Error handling subroutine.
:pathError
    echo.
    echo Error while refreshing the PATH variable:
    echo PathValue=%PathValue%
    echo UserPathValue=%UserPathValue%
    pause
    exit /b 2

endlocal
exit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接