Как я могу изменить Java-виртуальную машину Mac OS по умолчанию, возвращаемую из / usr / libexec / java_home


108

(Не был уверен, должно ли это происходить в SU ... переход, безусловно, возможен, но все больше программистов читают здесь вопросы, так что приступим).

Я использую Mac OS X 10.8.4, и у меня установлен Apple JDK 1.6.0_51, а также Oracle JDK 1.7.0_25. Недавно я установил предварительную версию JDK Oracle 1.8 для некоторого предварительного программного обеспечения, которое требует этого. Теперь, когда я запускаю / usr / libexec / java_home, я получаю следующее:

$ /usr/libexec/java_home -V
Matching Java Virtual Machines (4):
    1.8.0, x86_64:  "Java SE 8" /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home
    1.7.0_25, x86_64:   "Java SE 7" /Library/Java/JavaVirtualMachines/jdk1.7.0_25.jdk/Contents/Home
    1.6.0_51-b11-457, x86_64:   "Java SE 6" /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
    1.6.0_51-b11-457, i386: "Java SE 6" /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home

Отлично.

Однако бегущие:

$ java -version

Возврат:

java version "1.8.0-ea"

Это означает, что версия Java по умолчанию в настоящее время является предварительной версией, которая нарушает некоторые «нормальные» пакеты (в моем случае VisualVM).

Я не могу установить, JAVA_HOMEпотому что запускаемые приложения игнорируют переменные среды, даже при запуске из командной строки (например $ open /Applications/VisualVM.app).

Итак, есть ли файл, который я могу редактировать, где я могу глобально установить свои предпочтения упорядочивания JVM ?

(Пожалуйста, не говорите мне запускать панель настроек Java, потому что она просто не работает: она не содержит ничего полезного и содержит только одну из 4 JVM, которые я установил.)

Обновление :

JVM Oracle живут в /Library/Java/JavaVirtualMachines. Переименование каталога JDK 1.8 на jdk1.8.0.jvm.xyzничего не меняет: он по- java_homeпрежнему находится в нужном месте, а при запуске / usr / bin / java по-прежнему выполняется JVM 1.8. Это не проблема с синлинками и т. Д.

Ответы на похожие вопросы

Хотя этот ответ предлагает то, что составляет взлом, который удалит версии Java из подбора java_home, он все еще не отвечает на этот вопрос о том, как java_home выбирает свое значение по умолчанию и могут ли пользователи установить его неразрушающим образом .


Наберите which java и следуйте панировке. /usr/bin/javaэто просто символическая ссылка
Brian Roach

11
Был там, сделал это. /usr/bin/javaуказывает на /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java. VersionsКаталог не содержит символьную ссылку на 1.8.0 JDK. Вместо этого, он содержит каталог услужливо под названием , Aкоторое Currentуказывает. Aне является "JAVA_HOME. У него есть подкаталог, Commandsкоторый называется, в котором есть javaкоманда, но это непрозрачный универсальный двоичный файл, который делает неизвестно что. Я подозреваю, что он использует java_homeи т. д., чтобы решить, какую JVM использовать.
Кристофер Шульц

2
Если это не по теме, выполните миграцию вместо закрытия. FWIW, речь идет о «программных инструментах, обычно используемых программистами», поэтому закрывать «не по теме» - неискренне.
Christopher Schultz

Да, это неприятно! Мне просто нужен один JDK для всех или, может быть, два, чтобы я мог легко переключаться между 1,7 и 1,8.
Брайан

1
Я нашел этот SO-ответ полезным для этого вопроса: stackoverflow.com/a/44169445/2987755
dkb

Ответы:


89

Я думаю, JAVA_HOMEэто лучшее, что ты можешь сделать. Инструменты командной строки, такие как javaи javacбудут учитывать эту переменную среды, вы можете использовать, /usr/libexec/java_home -v '1.7*'чтобы дать вам подходящее значение для ввода JAVA_HOME, чтобы инструменты командной строки использовали Java 7.

export JAVA_HOME="`/usr/libexec/java_home -v '1.7*'`"

Но стандартные пакеты приложений с двойным щелчком вообще не используют установленные под ними JDK /Library/Java. Пакеты старого стиля, .appиспользующие Apple, JavaApplicationStubбудут использовать Apple Java 6 от /System/Library/Frameworks, а пакеты нового стиля, созданные с помощью AppBundler без встроенной JRE, будут использовать "общедоступную" JRE in /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home- это жестко запрограммировано в заглушке и не может быть изменено, и нельзя одновременно установить две разные общедоступные JRE.


Изменить: я специально изучил VisualVM, предполагая, что вы используете версию «пакета приложений» со страницы загрузки , и это конкретное приложение не является приложением AppBundler, вместо этого его основной исполняемый файл представляет собой сценарий оболочки, который вызывает номер других сценариев оболочки и читает различные файлы конфигурации. По умолчанию /Library/Javaон выбирает самый новый JDK, если это 7u10 или новее, или использует Java 6, если ваша установка Java 7 - это обновление 9 или более ранней версии. Но, разгадывая логику в сценариях оболочки, мне кажется, что вы можете указать конкретный JDK с помощью файла конфигурации.

Создайте текстовый файл ~/Library/Application Support/VisualVM/1.3.6/etc/visualvm.conf(замените 1.3.6 любой версией VisualVM, которую вы используете), содержащий строку

visualvm_jdkhome="`/usr/libexec/java_home -v '1.7*'`"

и это заставит его выбрать Java 7 вместо 8.


В моей системе этого не происходит. Запуск VisualVM до установки JDK 1.8 работал. После JDK1.8 VisualVM показывает экран-заставку, а затем умирает. Перемещение каталога JDK1.8 из / Library / Java восстанавливает его способность работать.
Christopher Schultz

@ChristopherSchultz Я заглянул внутрь пакета VisualVM, и оказалось, что это не обычное приложение appbundler. См. Мою правку для возможного обходного пути.
Ian Roberts

Извините, я написал свой предыдущий комментарий до вашего редактирования. Я проверю, как заставить VisualVM работать с использованием этого метода, но вряд ли он будет универсально применим. У меня есть куча другого программного обеспечения на основе Java, которое я также запускаю, например Eclipse, JasperReports iReport и т. Д., Которые, вероятно, будут затронуты этим. Я думаю, что лучше просто переместить каталог JDK1.8 в другое место и использовать его явно с JAVA_HOME в те (несколько) раз, когда мне это действительно нужно.
Christopher Schultz

1
Да, вы правы, это правильный JAVA_HOMEпуть, и в целом лучше всего указать младшую версию, которая вам нужна в других случаях. Основываясь на разборке, оказывается, что вы можете export JAVA_VERSION=1.7по java_homeумолчанию показывать JKD7 вместо JDK8, но это не работает, java_home -v 1.6потому что java-homeинтерпретирует его как дополнительное ограничение и отказывается из-за взаимно невыполнимых ограничений, а затем просто идет с 1,8 по умолчанию даже с --failfastопцией.
andrewdotn

2
Я не могу понять, почему панель управления Java System Preferences не просто представляет список для выбора, а не прибегает к сценариям / командам оболочки. Я подозреваю, что это только для апплетов, которые запускаются в браузере ...
JGFMK,

51

Я тоже был там и везде искал, как /usr/libexec/java_homeработает, но я не смог найти никакой информации о том, как он определяет доступные виртуальные машины Java, которые он перечисляет.

Я немного поэкспериментировал и думаю, что он просто выполняет, ls /Library/Java/JavaVirtualMachinesа затем проверяет ./<version>/Contents/Info.plistвсе среды выполнения, которые он там находит.

Затем он сортирует их по убыванию по ключу, JVMVersionсодержащемуся в Info.plist, и по умолчанию использует первую запись в качестве JVM по умолчанию.

Я думаю, что единственное, что мы могли бы сделать, это изменить plist: sudo vi /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Info.plistа затем изменить JVMVersion с 1.8.0на что-то еще, что заставит его сортировать его вниз, а не вверх, например !1.8.0.

Что-то вроде:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    ...
    <dict>
            ...
            <key>JVMVersion</key>
            <string>!1.8.0</string>   <!-- changed from '1.8.0' to '!1.8.0' -->`

а затем он волшебным образом исчезает из верхней части списка:

/usr/libexec/java_home -verbose
Matching Java Virtual Machines (3):
    1.7.0_45, x86_64:   "Java SE 7" /Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home
    1.7.0_09, x86_64:   "Java SE 7" /Library/Java/JavaVirtualMachines/jdk1.7.0_09.jdk/Contents/Home
    !1.8.0, x86_64: "Java SE 8" /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home

Теперь вам нужно будет выйти / войти в систему, а затем:

java -version
java version "1.7.0_45"

:-)

Конечно, я понятия не имею, сломается ли что-то еще или версия java 1.8.0-ea по-прежнему работает правильно.

Вероятно, вам не следует делать ничего из этого, а просто удалить 1.8.0.

Однако до сих пор это работало для меня.


Это сработало для меня. Мне пришлось использовать эту настройку, чтобы плагин Idea Sbt работал у меня на MacOS. Я упоминаю об этом в своем блоге agilebuild.blogspot.com/2014/02/…
антуан

Это работает, но кажется немного сложным и может не выглядеть как стандартная процедура. Блуждаю, если есть подход получше.
Weibo Li

Я все еще хотел бы найти решение для этого, но для настройки JDK для использования Intellij я добавил это в свой zshenv: export IDEA_JDK = /usr/libexec/java_home -v 1.7. Думаю, я сделаю то же самое для JAVA_HOME ...
Дэвид Резник

Мне удалось использовать этот ответ, чтобы избежать использования Java 9, запускающего приложения с двойным щелчком (из-за проблемы в проводнике хранилища ключей). Спасибо!
Nicolas Henneaux

2
Отрывок из « Установка JDK и JRE в macOS» : после установки Java для macOS 2012-006 /usr/bin/javaбудет найдена самая новая версия JDK, которая будет использоваться для всех связанных с Java инструментов командной строки в /usr/bin.
Джереми Као

7

На самом деле это довольно просто. Допустим, у нас есть это в нашей папке JavaVirtualMachines:

  • jdk1.7.0_51.jdk
  • jdk1.8.0.jdk

Представьте, что по умолчанию используется версия 1.8, затем мы просто добавляем новую папку (например, «старую») и перемещаем папку jdk по умолчанию в эту новую папку. Сделайте еще java -versionраз и вуаля, 1.7!


1
Невероятно, но это сработало ... Спасибо Mac OS Mojave
Michał

5

Это довольно просто, если вы не против закатать рукава ... / Library / Java / Home - это значение по умолчанию для JAVA_HOME, и это просто ссылка, указывающая на одно из:

  • /System/Library/Java/JavaVirtualMachines/1.?.?.jdk/Contents/Home
  • /Library/Java/JavaVirtualMachines/jdk1.?.?_??.jdk/Contents/Home

Поэтому я хотел изменить свою версию JVM / JDK по умолчанию, не изменяя содержимое JAVA_HOME ... / Library / Java / Home - стандартное расположение для текущей JVM / JDK, и это то, что я хотел сохранить ... мне кажется быть самым простым способом изменить ситуацию с наименьшими побочными эффектами.

На самом деле это действительно просто. Чтобы изменить версию java, которую вы видите с помощью java -version, все, что вам нужно сделать, это какая-то ее версия:

cd /Library/Java
sudo rm Home
sudo ln -s /Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home ./Home

Я не нашел времени, но очень простой сценарий оболочки, который использует / usr / libexec / java_home и ln для повторения указанной выше символической ссылки, должен быть глупо простым в создании ...

После того, как вы изменили расположение / Library / Java / Home ... вы получите правильный результат:

cerebro:~ magneto$ java -version
java version "1.8.0_60"
Java(TM) SE Runtime Environment (build 1.8.0_60-b27) Java HotSpot(TM)
64-Bit Server VM (build 25.60-b23, mixed mode)

1
Это не то, как это работает: /Library/Java/Homeэто действительно символическая ссылка, но она указывает на то, /System/Library/Frameworks/JavaVM.framework/Homeчто само находится в большом беспорядке символических ссылок, что, наконец, приводит вас к ... волшебной команде, которая определяет правильную JRE для запуска. Обратите внимание, что это /usr/libexec/java_homeтакже относится к этой магии. Итак, вы можете прервать все, просто заменив символические ссылки и указав на одну JRE, но вам придется обновлять ее каждый раз. Очевидно, нет команды вроде set_preferred_jvm_versionили чего-то подобного.
Кристофер Шульц,

1
Однако преимущество этой техники в том, что она не требует установки JAVA_HOMEгде-либо. Я поиграю с этой техникой, чтобы увидеть, приведет ли она к запуску программ на основе Java с «предпочтительной» виртуальной машиной Java. Я подозреваю, что будет, но он довольно хрупкий.
Кристофер Шульц,

Ну, в эти дни у меня есть только это .bash_profile:export JAVA_HOME=`/usr/libexec/java_home -v 12`
jrypkahauer

Это не работает для двойного щелчка по значку, в чем и заключалась вся суть. Решения, которые работают только из командной строки, не являются решениями.
Кристофер Шульц

3

У меня сработали инструкции Oracle по удалению Java 7 .

Выдержка:

Удаление JDK Чтобы удалить JDK, вы должны иметь права администратора и выполнить команду удаления либо от имени пользователя root, либо с помощью инструмента sudo (8).

Перейдите в / Library / Java / JavaVirtualMachines и удалите каталог, имя которого соответствует следующему формату: *

/Library/Java/JavaVirtualMachines/jdk<major>.<minor>.<macro[_update]>.jdk

Например, чтобы удалить 7u6:

% rm -rf jdk1.7.0_06.jdk


2
Этот вопрос не был о деинсталляции ... он был о выборе «основной» JVM из уже установленных ...
Кристофер Шульц

3

Немного поздно, но поскольку это постоянная проблема с Mac OSX ...

Самым простым решением, которое я нашел, было просто удалить файлы OpenJDK, которые устанавливает Apple. Каждый раз, когда приходит обновление Mac OSX, оно устанавливается, и вам нужно будет удалить его снова.

Это действительно хорошо работает, если вы разрабатываете приложения для Google App Engine на своем Mac с использованием Java. OpenJDK не работает должным образом, а версия Java, поставляемая с обновлением Mac OSX Yosemite, вызывает сбой подключаемого модуля Eclipse для App Engine при каждом развертывании с полезной ошибкой: «Истекло время чтения».


1
Забавно ... Я думал, что Apple полностью удалила Java. Я не помню, чтобы вручную удалил Java 1.6 JVM от Apple, и ее определенно больше нет. Во всяком случае, это на самом деле не решает исходную проблему, которая заключалась в том, чтобы указать предпочтительную JVM с учетом установленного выбора.
Кристофер Шульц

Ты прав. Это не отвечает на вопрос. Он отвечает на этот вопрос: если вы удалите используемую JVM, будет использоваться «следующая» из списка. Может, это поможет.
Mo'in Creemers

это объясняет, почему после запуска установки jdk 8 он не отображается в папке JavaVirtualMachines? Я вижу только «1.6.0.jdk», независимо от того, какую версию я устанавливаю.
whyoz

@whyoz Только что установил jdk-8u31-macosx-x64 на osx 10.10.2, и виртуальная машина была установлена ​​в папку JavaVirtualMachines, как и ожидалось.
Mo'in Creemers,

Вы случайно не запускаете Parallels? Я установил его на стороне Windows Parallels, и 8u31 установил, как ожидалось ... только не на стороне Mac ...
whyoz

3

Я безуспешно тестировал jenv и другие вещи, например установку JAVA_HOME. Теперь я и нашел следующее решение

function setJava {
    export JAVA_HOME="$(/usr/libexec/java_home -v $1)"
    launchctl setenv JAVA_HOME $JAVA_HOME
    sudo ln -nsf "$(dirname ${JAVA_HOME})/MacOS" /Library/Java/MacOS 
    java -version
}

(добавлен в ~ / .bashrc или ~ / .bash.profile или ~ / .zshrc)

И так зовут:

setJava 1.8

java_home обработает неправильный ввод. так что вы не можете сделать что-то не так. Maven и другие сотрудники сейчас подберут нужную версию.


1

Я на самом деле немного посмотрел на это в дизассемблере, так как исходный код недоступен.

В / usr / bin / java и / usr / libexec / java_home используется JavaLaunching.framework. Переменная среды JAVA_HOME действительно сначала проверяется / usr / bin / java и друзьями (но не / usr / libexec / java_home). Фреймворк использует переменные среды JAVA_VERSION и JAVA_ARCH для фильтрации доступных JVM. Итак, по умолчанию:

$ /usr/libexec/java_home -V
Matching Java Virtual Machines (2):
    11.0.5, x86_64: "Amazon Corretto 11"    /Library/Java/JavaVirtualMachines/amazon-corretto-11.jdk/Contents/Home
    1.8.0_232, x86_64:  "Amazon Corretto 8" /Library/Java/JavaVirtualMachines/amazon-corretto-8.jdk/Contents/Home

/Library/Java/JavaVirtualMachines/amazon-corretto-11.jdk/Contents/Home

Но установка, скажем, JAVA_VERSION может переопределить значение по умолчанию:

$ JAVA_VERSION=1.8 /usr/libexec/java_home
/Library/Java/JavaVirtualMachines/amazon-corretto-8.jdk/Contents/Home

Вы также можете установить JAVA_LAUNCHER_VERBOSE = 1, чтобы увидеть некоторые дополнительные журналы отладки, касающиеся путей поиска, найденных JVM и т. Д., С обоими / usr / bin / java и / usr / libexec / java_home.

В прошлом JavaLaunching.framework фактически использовал систему настроек (в домене com.apple.java.JavaPreferences) для установки предпочтительного порядка JVM, позволяя установить JVM по умолчанию с помощью PlistBuddy - но насколько я могу судить, это код был удален в последних версиях macOS. Переменные среды кажутся единственным выходом (помимо редактирования Info.plist в самих пакетах JDK).

Установка переменных среды по умолчанию, конечно, может быть выполнена через ваш .profile или с помощью launchd , если вам нужно, чтобы они были установлены на уровне сеанса.


Это отличная информация, Дэн. Использование .profileбесполезно для моего варианта использования (запуск приложения, например, с панели запуска), но подсказка launchdхорошая. Мне придется попробовать, поскольку недавнее безумие Java по управлению версиями означает, что у меня одновременно установлено несколько поколений Java с разным уровнем (личного) доверия.
Кристофер Шульц

-2

Изменить: эта информация предназначена специально для visualvm, а не для любого другого приложения java.

Как уже упоминалось другими, вам необходимо изменить visualvm.conf

Для последней версии JvisualVM 1.3.6 на Mac каталоги установки изменились.

В настоящее время он находится в /Applications/VisualVM.app/Contents/Resources/visualvm/etc/visualvm.conf .

Однако это может зависеть от того, где вы установили VisualVM. Самый простой способ найти, где ваш VisualVM - запустить его, а затем посмотреть на процесс, используя:

ps -ef | grep VisualVM

Вы увидите что-то вроде:

... -Dnetbeans.dirs = / Applications / VisualVM.app / Contents / Resources / visualvm / visualvm ...

Вы хотите взять свойство netbeans.dir и найти каталог, и вы найдете папку etc.

Раскомментируйте эту строку в visualvm.conf и измените путь к jdk

visualvm_jdkhome="/path/to/jdk"

Кроме того, если у вас медленная работа с вашим visualvm и у вас много памяти, я бы предложил значительно увеличить объем доступной памяти и запустить его в режиме сервера:

visualvm_default_options="-J-XX:MaxPermSize=96m -J-Xmx2048m -J-Xms2048m -J-server -J-XX:+UseCompressedOops -J-XX:+UseConcMarkSweepGC -J-XX:+UseParNewGC -J-XX:NewRatio=2 -J-Dnetbeans.accept_license_class=com.sun.tools.visualvm.modules.startup.AcceptLicense -J-Dsun.jvmstat.perdata.syncWaitMs=10000 -J-Dsun.java2d.noddraw=true -J-Dsun.java2d.d3d=false"

Плохой совет: изменение сценария запуска для конкретного приложения, скорее всего, сломает приложение и не решит исходную проблему изменения JVM по умолчанию для ОС.
Кристофер Шульц

К сожалению, как упоминалось другими, jvisualvm не использует стандартные методы для выбора jvm. Это единственное решение для этого приложения.
Celandro 06

Как я заявляю в своем ответе, вам не нужно ничего изменять внутри самого пакета приложения, приложение может загружать свою конфигурацию из ~/Library/Application Support/VisualVM/1.3.6/etc/visualvm.conf.
Ян Робертс

-2

У меня была похожая ситуация, и у меня сработал следующий процесс:

  1. В терминале введите

    vi ~/.profile
  2. Затем добавьте эту строку в файл и сохраните

    export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk<version>.jdk/Contents/Home

    где версия - это версия на вашем компьютере, например 1.7.0_25

  3. Выйдите из редактора, затем введите следующую команду, чтобы она вступила в силу

    source ~/.profile 

Затем введите java -version, чтобы проверить результат

    java -version 

Что такое .profile? Источник: http://computers.tutsplus.com/tutorials/speed-up-your-terminal-workflow-with-command-aliases-and-profile--mac-30515

.profile - это скрытый файл. Это необязательный файл, который сообщает системе, какие команды запускать, когда пользователь, чей файл профиля находится в системе, входит в систему. Например, если мое имя пользователя - bruno, а файл .profile находится в / Users / bruno /, все его содержимое будет выполняться во время процедуры входа в систему.


Это не сработает при запуске VisualVM из Launchpad. Запуск из командной строки никогда не является проблемой, поскольку вы можете установить переменную среды JAVA_HOME.
Кристофер Шульц

-2

MacOS использует / usr / libexec / java_home для поиска текущей версии Java. Один из способов обойти - изменить файл plist, как описано выше в @ void256. Другой способ - сделать резервную копию java_home и заменить ее своим собственным скриптом java_home с кодом
echo $ JAVA_HOME

Теперь экспортируйте JAVA_HOME в нужную версию SDK, добавив следующие команды в ~ / .bash_profile. export JAVA_HOME = "/ System / Library / Java / JavaVirtualMachines / 1.6.0.jdk / Contents / Home" launchctl setenv JAVA_HOME $ JAVA_HOME /// Сделайте переменную среды глобальной

Запустите источник команды ~ / .bash_profile для выполнения вышеуказанных команд.

Каждый раз, когда нужно изменить JAVA_HOME, он может сбросить значение JAVA_HOME в файле ~ / .bash_profile.


Все, что зависит от переменных среды, работать не будет. Дело в том, что приложения, запускаемые через LaunchPad и т. Д., Не имеют такой настройки среды. Приведенный выше метод plist кажется "лучшим" в том смысле, что он действительно дает желаемый результат. Я пока не уверен в минусах. См. Ответ от @Tony, у которого такая же проблема.
Christopher Schultz

-3

Я хотел изменить версию Java по умолчанию с 1.6 * на 1.7 *. Я попробовал следующие шаги, и у меня это сработало:

  • Удалена ссылка "java" из-под / usr / bin
  • Создал его снова, указав на новое место:

ln -s /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/bin/java java

  • проверено с помощью "java -version"

java версия "1.7.0_51"
Java (TM) SE Runtime Environment (сборка 1.7.0_51-b13
) 64-разрядная серверная виртуальная машина Java HotSpot (TM) (сборка 24.51-b03, смешанный режим)


Не отвечает на вопрос: не повлияет на поведение /usr/libexec/java_home.
Кристофер Шульц
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.