Working with windows in java

How to switch Java versions in Windows (updated 03/2021 for Java 16)

As a Java programmer, I work on various projects based on different Java versions, especially since the transition to the six-month release cycle. From time to time, I also have a piece of Java code that I want to try out on different Java versions – on the command line without having to click through the menus of my IDE. So it is helpful to be able to quickly and easily change the Java version to be used for compiling code or executing class files.

In this article, I’ll show you how to install several Java versions simultaneously in Windows and how to switch between them on the command line with short commands.

Installation of multiple Java versions

Installing several Java versions at the same time is incredibly easy in Windows. You can download and run the installer for each version, which automatically installs the versions in separate directories.

Download sources

  • Java SE 1.1 – You can no longer install this version on 64-bit Windows.
  • Java SE 1.2 – Installed to C:\jdk1.2.2\ and C:\Program Files (x86)\JavaSoft\JRE\1.2\ by default – I recommend changing this to C:\Program Files (x86)\Java\jdk1.2.2\ and C:\Program Files (x86)\Java\jre1.2.2\ for the sake of clarity.
  • Java SE 1.3 – Installed to C:\jdk1.3.1_28\ by default – I recommend changing this to C:\Program Files (x86)\Java\jdk1.3.1_28\ .
  • Java SE 1.4 – Installed to C:\j2sdk1.4.2_19\ by default – I recommend changing this to C:\Program Files (x86)\Java\jdk1.4.2_19\ .

Starting with the following versions, you don’t need to change the default installation directories:

Attention – you may use the following Oracle distributions only for private purposes and development:

The following version is currently an early access build. You should use it only for testing purposes:

Environment variables

In most cases, the following two environment variables decide which Java version an application uses:

  • JAVA_HOME – many start scripts use this variable.
  • Path – is used when running a Java binary (such as java and javac ) from the console.

These variables should always point to the same Java installation to avoid unforeseen problems due to inconsistencies. Some programs, such as Eclipse, define the Java version in a separate configuration file (for Eclipse, for example, this is the entry «-vm» in the eclipse.ini file).

Setting environment variables manually

The installers of the Java versions listed above already create various environment variables, which you need to clean up first (see below). The fastest way to change the environment variables is to press the Windows key and type «env» – Windows then offers «Edit the system environment variables» as a search result:

At this point, you can press «Enter,» and the system properties appear:

Here you click on «Environment Variables…», after which the following window opens:

As the standard version, I currently use the latest release version, Java 16. Therefore, you should make the following settings:

  • The top list («User variables») should not contain any Java-related entries.
  • The lower list («System variables») should contain an entry «JAVA_HOME = C:\Program Files\Java\jdk-16\» (please check the version number, you may have a newer one). If this entry does not exist, you can add it with «New…». If it exists, but points to another directory, you can change it with «Edit…».
  • Delete the following entries under «Path»:
    • C:\ProgramData\Oracle\Java\javapath
    • C:\Program Files (x86)\Common Files\Oracle\Java\javapath
  • Insert the following entry instead:
    • %JAVA_HOME%\bin
Читайте также:  Intel gm45 driver windows 10

The path list should then look like this:

The last entry ensures that Path and JAVA_HOME are automatically consistent. Attention: this only works for the default setting configured here. If you change JAVA_HOME via the command line, you have to adjust Path accordingly (more about this below).

Now open a command line to check the settings with the following commands:

As a result, you should see this:

Scripts for changing the Java version

Finally, we come to the possibility to change the Java version quickly and easily. Therefore I create a separate command for each Java version, called, for example, java16 , java15 , java14 , java13 . I put these commands in the directory C:\Program Files\Java\scripts , which I add to the environment variable «Path» as described before:

The files are named, for example, java16.bat , java15.bat , java14.bat , java13.bat , and change the environment variables as shown in the following example of java16.bat :

This script, admittedly kept very simple, inserts the bin directory of the Java version to be activated at the beginning of the Path variable, so that is where, for example, java.exe is looked for first. The path variable becomes longer with each switching. However, since this is only the case for the currently opened command prompt, I don’t think this is a problem.

The following ZIP file contains all my scripts from Java 1.2 to Java 17 (you might have to adopt one or the other Java directory to your installation): scripts-up-to-jdk17.zip

You can quickly test whether the scripts work in a command line. Attention: after adding the scripts directory to the Path variable, you have to open a new command line.

At this point, the setup is complete. I hope this article was helpful for you, and I’d love to hear your comments. If you liked the article, I’d be happy if you shared it via one of the following share icons.

Working with Windows registry using java.util.prefs.Preferences

I have some questions about the registry.
We have

it will return true.
After it:

We see that it has one child: «Windows». But

returns false. Why?

UPDATE

Ok. I have some mistakes. Let me try again: Why does

2 Answers 2

If you execute the code lines shown, in the order shown, when you get to the line

p does not anymore point to the user root, but to «/HKEY_CURRENT_USER/Software/Policies».

Btw you have a probable omission in your third code sample:

I stumbled on this one today. The answer you’ve accepted is completely wrong.

You seem to be under the impression that Java Preferences is a general tool to manipulate the Windows Registry. It is not. It just so happens that the default implementation of Preferences on the Windows platform happens to store its data in the Windows Registry.

The implementation on Windows stores stuff under the following Registry paths:

For systemRoot: HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Prefs

For userRoot : HKEY_CURRENT_USER\Software\JavaSoft\Prefs

(note: The registry paths changes a bit if you are using a 32bit JRE on a 64-bit OS but that has nothing to do with Java and everything to do with Windows. Sun’s code always use the above paths.)

The point to make is that you can maybe use Java Preferences interface to read or change values in the Windows Registry but only below the above registry paths. The reason why I say ‘maybe’ is that this is just how it happens to be at the moment. Sun/Oracle could at any point in time decide to not to use the Windows Registry or use the Windows Registry but without using sub-nodes, i.e. store everything in one big XML string or something. The point is that Java Preferences is designed to shield you from this.

Читайте также:  Making link in linux

A lot of Java software that use the Java Preferences provide their own implementation (which is pretty simple to do) to avoid Sun’s default implementation that uses the Windows Registry. Not everyone can write to the Windows Registry these days so that was a pretty bad design decision on Sun’s part. Fortunately very easy to change.

Создание Windows службы на Java

February 22, 2019 Jazz Team Технические статьи

Введение

В рамках одного из проектов требовалось разработать Windows службу, которая могла бы выполнять ряд действий с помощью Windows API, Websocket и стандартных средств Java. Далее в статье будут описаны шаги, которые были сделаны для создания такой службы.
Потребность в Windows службе возникла из-за необходимости иметь программу со следующими возможностями:

  • она должна быть постоянно запущена,
  • выполнялась от системного пользователя,
  • автоматически запускалась при старте системы,
  • чтобы её сложно было остановить обычному пользователю.

Создание минимизированной версии JRE

Так как GraalVM всё ещё не поддерживает создание исполняемых файлов под Windows, было решено воспользоваться другими возможностями, которые предоставляет экосистема Java, а именно создание минимизированной версии JRE.

Для того, чтобы создать минимизированную версию JRE, для начала необходимо узнать зависимости на определенные пакеты, которые будут включены в JRE.

В первую очередь необходимо собрать jar-файл “fat jar” со всеми зависимостями.

Затем выполнить команду jdeps -s , чтобы получить список всех зависимостей. Например:

Далее создаём нашу версию JRE с данными зависимостями:

jlink –module-path –add-modules

java.base,java.datatransfer,java.desktop,java.logging,java.net.http,java.sql,java.xml,jdk.unsupported –strip-debug –compress 2 –no-header-files –no-man-pages –output

Обратите внимание, что перечисление пакетов для опции –add-modules необходимо разделять запятой и не ставить между ними пробелов. Остальные опции отвечают за сжатие и убирание файлов и другой информации, которая не пригодится для выполнения программы.

После выполнения этих действий JRE будет занимать порядка 30 mb, вместо сотен.

Создание Windows службы из любого приложения

Java не имеет стандартных средств по созданию служб, поэтому были изучены сторонние инструменты и был выбран WinSW в силу его бесплатности и простоты использования.

WinSW

WinSW – это утилита, которая позволяет запустить и обернуть любой процесс как Windows службу. Для того, чтобы начать с ней работать, необходимо скачать исполняемый и конфигурационный файлы по этой ссылке https://github.com/kohsuke/winsw/releases.

Необходимо поместить эти два файла в директорию. Переименовать исполняемый файл на своё усмотрение и дать такое же название файлу конфигурации, затем поместить в эту директорию jar-файл приложения и созданную JRE.

В конфигурационном файле необходимо прописать минимальную конфигурацию:

jre\bin\java.exe – относительный путь внутри нашей папки к исполняемому файлу нашей JRE.

После этих действий можно установить службу, для этого необходимо выполнить команду от имени администратора:

Список команд можно посмотреть здесь .

Взаимодействие Java и Windows API

Для использования функций Windows (таких как создание нового процесса или добавление ключей реестра) в нашем приложении был использован JNA.
JNA (Java Native Access) предоставляет Java-программам легкий доступ к библиотекам, написанным на другом языке, без написания чего-либо, кроме кода Java. JNA позволяет напрямую вызывать нативные функции, используя обычный вызов метода Java. Большинство методов не требуют специальной обработки или конфигурации; не требуется шаблон или сгенерированный код.
Подключить и работать с JNA очень просто, для этого необходимо скачать jar-файл или подключить зависимость в сборщик проекта – в нашем случает Maven:

В нашем проекте мы использовали JNA для достижения следующих целей: заблокировать и сделать вновь доступным диспетчер задач 1) по комбинации Ctrl+Shift+Esc и 2) в меню, доступном по комбинации Ctrl+Alt+Del.

Читайте также:  Перестал работать сканер отпечатков пальцев windows 10

Для достижения этого были использованы класс Advapi32Util (удобная обёртка над библиотекой advapi32.dll) и интерфейс WinReg с полезными константами , которые предоставляют функциональность для внесения изменений в реестр Windows (Рисунок 1. Класс TaskManager с методами enable() и disable() для изменения ключей реестра диспетчера задач).

Рисунок 1. Класс TaskManager с методами enable() и disable() для изменения ключей реестра диспетчера задач.

  • Создать новый процесс от имени определённого пользователя Windows. Для этого мы использовали метод CreateProcessAsUser()интерфейса Advapi32. В метод необходимо передать следующие параметры:
    • hToken – дескриптор токена пользователя, для которого мы запускаем процесс.
    • lpApplicationName – имя модуля, который должен быть выполнен.
    • lpCommandLine – командная строка для выполнения.
    • lpProcessAttributes – указатель на структуру SECURITY_ATTRIBUTES, которая определяет дескриптор безопасности для нового объекта процесса и определяет, могут ли дочерние процессы наследовать возвращенный дескриптор процесса.
    • lpThreadAttributes – указатель на структуру SECURITY_ATTRIBUTES, который определяет дескриптор безопасности для нового объекта потока и определяет, могут ли дочерние процессы наследовать возвращенный дескриптор потока.Создать новый процесс от имени определённого пользователя Windows. Для этого мы использовали метод CreateProcessAsUser() интерфейса Advapi32. В метод необходимо передать следующие параметры:
    • bInheritHandles – если этот параметр TRUE, каждый наследуемый дескриптор вызывающего процесса наследуется новым процессом. Если параметр FALSE, процессы не наследуются.
    • dwCreationFlags – флаги, которые контролируют класс приоритета и создают процесс.
    • lpEnvironment – указатель на блок среды для нового процесса. Если этот параметр равен NULL, новый процесс использует среду вызывающего процесса. Блок среды состоит из блока с нулевым завершением строк с нулевым завершением. Каждая строка имеет следующий вид: name = value \ 0.
    • lpCurrentDirectory – полный путь к текущему каталогу для процесса. Строка также может указывать путь UNC (universal naming convention).
    • lpStartupInfo – указатель на структуру STARTUPINFO или STARTUPINFOEX.lpProcessInformation – указатель на структуру PROCESS_INFORMATION, которая получает идентификационную информацию о новом процессе.

Рисунок 2. Метод для создания нового процесса для определённого пользователя Windows.

  • Получить токен активного пользователя, т.к. он необходим для создания процесса от определённого пользователя.

Работа с процессами

Для работы и слежения за процессами в Windows был использован, добавленный в Java 9, класс ProcessHandle. ProcessHandle позволяет получать и производить различные манипуляции с процессами. В частности, при решении задачи, требовалось собирать PID процессов, фильтровать процессы на основе имени и принудительно завершать необходимые процессы.

Рисунок 3. Класс ProcessHandler с методами takeSnapshot() для создания снимка текущих процессов и closeNewProcesses() для завершения процессов, отличных от снимка.

Взаимодействие с другими компонентами системы

WebSocket

Для Java существует стандартизированный API для работы с WebSocket.

Но одного API недостаточно, поэтому для запуска кода была выбрана одна из его реализаций – Tyrus.

Далее можно создать минималистичный сервер и указать обработчики (EndPoints).

Заготовка обработчика выглядит следующим образом:

HTTP-клиент

С выпуском 11-ой версии Java в ней появился удобный HTTP-клиент, поэтому потребность в сторонних клиентах исчезла.

Для создания экземпляра клиента необходимо воспользоваться билдером. В простейшем случае:

Далее необходимо создать запрос(request), например:

Затем этот запрос можно использовать для отправки на сервер:

Заключение

Благодаря модульной организации версий Java 9 и выше, утилите WinSW, обновлённому Process API для взаимодействия с процессами операционной системы и библиотеки JNA (Java Native Access), которая предоставляет программам Java простой доступ к нативным библиотекам, мы смогли создать Windows службу с использованием языка Java, на котором была реализована и серверная часть. Что в итоге позволило не вводить в процесс разработки новый язык.

Оцените статью