在 Windows 中切换不同的 JDK 版本

Posted

技术标签:

【中文标题】在 Windows 中切换不同的 JDK 版本【英文标题】:Switching between different JDK versions in Windows 【发布时间】:2015-01-15 13:40:23 【问题描述】:

我正在处理几个项目,其中一些项目使用不同的 JDK。在 JDK 版本之间切换并不方便。所以我想知道是否有任何简单的方法可以改变它?

我找到了2种方法,应该可以解决这个问题,但它不起作用。

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

@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

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

我发现的第二个解决方案是来自this 站点的应用程序。而且它也不起作用。效果与第一种解决方案相同。

有什么想法吗?因为通过以下方式更改 JAVA_HOME 和 PAHT:Win + Pause -> Advanced System Settings -> Environment Variables -> 并编辑这些变量,这是一种糟糕的方式......

【问题讨论】:

用批处理文件设置路径,在批处理文件中也执行java。 如您所见,这两个变量都在批处理文件中设置。但我不知道如何在这个文件中执行 java。我在另一个页面上找到了这个解决方案,我不知道如何编写批处理文件。 【参考方案1】:

set 命令仅适用于当前终端。要永久设置系统或用户环境变量,您可以使用setx

setx JAVA_HOME "C:\Program Files\Java\jdk1.7.0_72" /m

/m 选项用于设置系统范围的变量(而不仅仅是当前用户)。终端必须以管理员身份运行才能使用此选项。

该变量将在所有新终端窗口中可用,但在当前窗口中不可用。如果要在同一个窗口中显示路径,则需要同时使用setsetx

如果您只将 %JAVA_HOME% 放入其中,而不是完整的 JDK 路径,则可以避免操作 PATH 变量。如果您更改JAVA_HOMEPATH 也会更新。


还有一些环境变量编辑器可以替代繁琐的 Windows 环境变量设置。请参阅超级用户上的“Is there a convenient way to edit PATH in Windows 7?”。

【讨论】:

嗯,出了点问题......我按照你说的做了,它添加了这些变量,但是对于用户......仍然当我打开新终端时,我得到的信息是我有不同的 JDK,而不是我想要的... 缺少 /m 选项,我已经更新了答案。 我是否还必须将第二个“set”替换为“setx”(行:set PATH=C:\Program Files\Java\jdk1.7.0_72\bin;%PATH%)? @OddDev 如果你想永久更改 PATH,你也需要在那里使用setx。不过,它会在您每次运行脚本时添加 java 路径,因此最好删除该行并将%JAVA_HOME% 添加到 PATH 中一次 终端或应用程序需要重新启动以考虑到由更新的JAVA_HOME 引起的PATH 的变化。或***.com/questions/171588/…【参考方案2】:

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

使用以下代码创建批处理文件。您可以使用 if 和 else 块添加 n 个版本。

@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。

我希望这对想要经常更改它的人有所帮助。

【讨论】:

【参考方案3】:
    打开Environment Variables编辑器(文件资源管理器>右键单击 这台电脑 > 属性 > 高级系统设置 > 环境 变量...) 在系统变量列表中找到Path变量> 按编辑 > 将%JAVA_HOME%bin; 放在第一位。这是必需的 因为 Java 安装程序将 C:\Program Files (x86)\Common Files\Oracle\Java\javapath 添加到 PATH 中,该 PATH 引用了已安装的最新 Java 版本。

    现在您可以使用setx 命令在 Java 版本之间切换(应该在管理权限下运行):

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

    (注意:行尾没有双引号,不应该这样,否则你会在JAVA_HOME 变量中得到c:\Program Files\Java\jdk-10.0.1\",它会破坏你的PATH 变量)

具有系统变量(和管理权限)的解决方案更加健壮,因为它将所需的 Java 路径放在生成的 PATH 变量的开头。

【讨论】:

【参考方案4】:

如果您的路径少于 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 的一些输入来修改此脚本

【讨论】:

【参考方案5】:

运行这个 BAT 文件可以方便地更改 java 版本。

优点:

    它不会修改 PATH 系统环境变量。 唯一需要维护的是关系数组(可以方便地构造为稀疏数组),其中包含脚本开头的版本号和路径。

前提条件:

以下条目 %JAVA_HOME%\bin 必须是 appended 到 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

【讨论】:

【参考方案6】:

在 PowerShell 开始时加载下面提到的 PowerShell 脚本。或使用New-Item $profile -Type File -Force 生成文件 这将在这里创建一个文件C:\Users\user_name\Documents\WindowsPowerShell\Microsoft.PowerShell_profile

现在将下面给出的内容复制粘贴到此文件中,以便在每次启动 PowerShell 时加载

将您需要的所有 java 版本设置为单独的变量。

    Java_8_home-> 指向本地的 Java 8 位置 Java_11_home -> 指向本地的 Java 11 位置 Java_17_home -> 指向本地 Java 17 位置 Java_Home->这里指向你要使用的java版本

在power shell中运行更新版本为8update_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")

【讨论】:

以上是关于在 Windows 中切换不同的 JDK 版本的主要内容,如果未能解决你的问题,请参考以下文章

骚操作:windows多版本jdk快速切换!!!

骚操作:windows多版本jdk快速切换!!!

ubuntu中 不同JDK版本之间的切换

Windows jdk安装以及版本切换

解决Windows对JDK默认版本切换问题

JavaJDK 版本切换(Windows)