Перейти к основному содержимому

Безголовый режим Java

· 4 мин. чтения

1. Обзор

Иногда нам нужно работать с графическими приложениями на Java без фактического дисплея, клавиатуры или мыши , скажем, на сервере или в контейнере. **

**

В этом кратком руководстве мы собираемся узнать о безголовом режиме Java для решения этого сценария. Мы также посмотрим, что мы можем делать в безголовом режиме, а что нет.

2. Настройка безголового режима

Есть много способов явно настроить безголовый режим в Java:

  • Программная установка системного свойства java.awt.headless в значение true
  • Используя аргумент командной строки: java -Djava.awt.headless=true
  • Добавление -Djava.awt.headless=true к переменной среды JAVA_OPTS в сценарии запуска сервера

Если среда на самом деле безголовая, JVM будет знать об этом неявно. Однако в некоторых сценариях будут небольшие различия. Мы скоро увидим их.

3. Примеры компонентов пользовательского интерфейса в автономном режиме

Типичным примером использования компонентов пользовательского интерфейса, работающих в автономной среде, может быть приложение для преобразования изображений. Хотя для обработки изображений ему нужны графические данные, дисплей на самом деле не нужен. Приложение можно запускать на сервере и преобразовывать файлы, сохраненные или отправленные по сети, на другой компьютер для отображения.

Давайте посмотрим на это в действии.

Во-первых, мы включим безголовый режим программно в классе JUnit :

@Before
public void setUpHeadlessMode() {
System.setProperty("java.awt.headless", "true");
}

Чтобы убедиться, что он настроен правильно, мы можем использовать java.awt.GraphicsEnvironment # isHeadless :

@Test
public void whenSetUpSuccessful_thenHeadlessIsTrue() {
assertThat(GraphicsEnvironment.isHeadless()).isTrue();
}

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

Теперь давайте посмотрим на наш простой конвертер изображений:

@Test
public void whenHeadlessMode_thenImagesWork() {
boolean result = false;
try (InputStream inStream = HeadlessModeUnitTest.class.getResourceAsStream(IN_FILE);
FileOutputStream outStream = new FileOutputStream(OUT_FILE)) {
BufferedImage inputImage = ImageIO.read(inStream);
result = ImageIO.write(inputImage, FORMAT, outStream);
}

assertThat(result).isTrue();
}

В следующем примере мы видим, что информация обо всех шрифтах, включая метрики шрифтов, также доступна нам:

@Test
public void whenHeadless_thenFontsWork() {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
String fonts[] = ge.getAvailableFontFamilyNames();

assertThat(fonts).isNotEmpty();

Font font = new Font(fonts[0], Font.BOLD, 14);
FontMetrics fm = (new Canvas()).getFontMetrics(font);

assertThat(fm.getHeight()).isGreaterThan(0);
assertThat(fm.getAscent()).isGreaterThan(0);
assertThat(fm.getDescent()).isGreaterThan(0);
}

4. Безголовое исключение

Есть компоненты, которые требуют периферийных устройств и не будут работать в автономном режиме. Они вызывают исключение HeadlessException при использовании в неинтерактивной среде:

Exception in thread "main" java.awt.HeadlessException
at java.awt.GraphicsEnvironment.checkHeadless(GraphicsEnvironment.java:204)
at java.awt.Window.<init>(Window.java:536)
at java.awt.Frame.<init>(Frame.java:420)

Этот тест утверждает, что использование Frame в безголовом режиме действительно вызовет исключение HeadlessException :

@Test
public void whenHeadlessmode_thenFrameThrowsHeadlessException() {
assertThatExceptionOfType(HeadlessException.class).isThrownBy(() -> {
Frame frame = new Frame();
frame.setVisible(true);
frame.setSize(120, 120);
});
}

Как правило, помните, что компоненты верхнего уровня, такие как Frame и Button , всегда нуждаются в интерактивной среде и будут вызывать это исключение. Однако это будет выдано как неисправимая ошибка , если безголовый режим не установлен явно .

5. Обход тяжеловесных компонентов в безголовом режиме

В этот момент мы могли бы задать себе вопрос — но что, если у нас есть код с компонентами графического интерфейса для работы в обоих типах сред — на рабочей машине с головкой и на безголовом сервере анализа исходного кода?

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

Итак, мы можем использовать условный подход:

public void FlexibleApp() {
if (GraphicsEnvironment.isHeadless()) {
System.out.println("Hello World");
} else {
JOptionPane.showMessageDialog(null, "Hello World");
}
}

Используя этот шаблон, мы можем создать гибкое приложение, которое регулирует свое поведение в зависимости от среды.

6. Заключение

На разных примерах кода мы увидели, как и почему безголовый режим в java. В этой технической статье представлен полный список того, что можно делать при работе в автономном режиме.

Как обычно, исходный код приведенных выше примеров доступен на GitHub .