关于java:JavaThe-Java-Headless-Mode

75次阅读

共计 6228 个字符,预计需要花费 16 分钟才能阅读完成。

原文

https://www.baeldung.com/java-headless-mode

引言

这篇文章源自集体看到了 Kafka 的启动脚本中一个“奇怪”的参数:

-Djava.awt.headless=true

拿去谷歌一下发现网上的形容都大差不差,这里找了 baeldung(相似国外的菜鸟教程)中的一篇文章,本文内容来自于英文博客原文。

这篇文章介绍了 -Djava.awt.headless 参数的作用,网上大部分的材料都是说“为了 进步计算效率和适配性 咱们能够应用这种模式,敞开图形显示等性能能够大大节俭设施的计算能力,而且对一些自身没有相干显示设施的机器也能适配,程序也能够失常运行。”,集体认为这些实践内容不太能了解。

当然也有诸如 服务器没有显示屏什么的,你得通知程序一声,你工作的中央没有这些设施 这种说法,为此找了一篇国外的博客介绍。

如何设置?

设置形式如下:

  • 在 system property 中设置 _java.awt.headless_ 为 _true_。

SpringBoot 的源码中能够找到相似的代码:

private void configureHeadlessProperty() {System.setProperty("java.awt.headless", System.getProperty("java.awt.headless", Boolean.toString(this.headless)));
    }
  • 启动脚本中进行设置-Djava.awt.headless=true:在 Kafka 的脚本当中存在相似的启动脚本。
KAFKA_JVM_PERFORMANCE_OPTS="-server -XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:+ExplicitGCInvokesConcurrent -XX:MaxInlineLevel=15 -Djava.awt.headless=true"

最初一个参数显示它应用 headless 模式。

  • 在执行命令的时候动静增加-Djava.awt.headless=true,这种形式和脚本设置启动的形式相似。

Headless 绕过重量级组件

如果一个带有 GUI 组件的代码在开和关 Headless 模式下运行别离会有什么不同的成果?

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

下面的代码如果敞开了 Headless 模式,则打印 Hello World 会变为图形化界面。

如果开启 Headless,则会打印在控制台。

Headless Mode 在 UI 组件的利用案例

Java Headless Mode 的典型案例可能是应用图形转化器,咱们有时候可能须要图形数据进行图像处理,然而不肯定须要理论显示。

上面通过一个单元测试来模仿这些状况:

  @Before  
    public void setUpHeadlessMode() {  
        // 通过正文掉上面的代码测试不同的成果  
//        System.setProperty("java.awt.headless", "true");  
    }  
  
    @Test  
    public void whenSetUpSuccessful_thenHeadlessIsTrue() {boolean headless = GraphicsEnvironment.isHeadless();  
        Assert.assertTrue(headless);  
    }/*  
    测试通过  
    正文上面的代码之后,单元测试不通过  
    //        System.setProperty("java.awt.headless", "true");    */

应用 awt 的组件java.awt.GraphicsEnvironment#isHeadless,留神较高版本的 JDK(例如 JDK11)中 awk 被间接干掉了,须要下载内部依赖导入才能够应用,倡议抉择 JDK8 以及以下的版本测试下面的程序。

下面的代码如果正文掉 headless 模式,单元测试会间接不通过。上面简略构建了一个图形转化器:

@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);  
    }

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 来进行验证:

  
   @Test  
   public void whenHeadlessmode_thenFrameThrowsHeadlessException() {Frame frame = new Frame();  
       frame.setVisible(true);  
       frame.setSize(120, 120);  
   }/*  
   在开关 Headless 模式后会有不同的后果  
   开启:通过      
   
   敞开  
   ava.awt.HeadlessExceptionat java.awt.GraphicsEnvironment.checkHeadless(GraphicsEnvironment.java:204)  
at java.awt.Window.<init>(Window.java:536)  
at java.awt.Frame.<init>(Frame.java:420)  
at java.awt.Frame.<init>(Frame.java:385)  
  
   */

作为一个教训法令,请记住,像 Frame 和 Button 这样的顶级组件总是须要一个交互式的环境,并且会抛出这个异样。然而,如果没有明确设置无头模式,它将被抛出,成为一个不可复原的谬误。

总结

通过代码和案例剖析,咱们大抵理解 Java Headless Mode 模式是怎么一回事,说白了就是屏蔽掉外置设施比方 GUI 的额定开销,转而用程序本人去进行模仿。

Kafka 设置这样的参数就是把性能施展到机制,摈弃所有外部设备烦扰,让服务器尽可能的通过本身程序模仿外部设备。

比方重量级组件控制台打印,在内部设计能够通过 JOptionPane 的 GUI 组件实现可视化成果,而 Headless 则是利用咱们熟知的 System.out 控制台输入输出流实现打印性能的模仿。

以上就是对于 Java Headless Mode 的了解。

程序 demo

本文的集体试验代码放到上面局部,文章提到的局部代码可能会无奈编译通过(图形转化器的代码),集体了解代码用意之后就没有深究了,读者碰到报错问题疏忽删除即可。

PS:倡议应用 JDK8 之前的版本,能够间接引入 awt 和 swing 的相干组件。

  
import jdk.nashorn.internal.ir.LiteralNode;  
import org.junit.Assert;  
import org.junit.Before;  
import org.junit.Test;  
  
import javax.imageio.ImageIO;  
import javax.swing.*;  
import java.awt.*;  
import java.awt.image.BufferedImage;  
import java.io.FileOutputStream;  
import java.io.IOException;  
import java.io.InputStream;  
  
import static org.junit.Assert.assertThat;  
  
  
public class HandlessTest {  
  
    @Before  
    public void setUpHeadlessMode() {  
        // 通过正文掉上面的代码测试不同的成果  
        System.setProperty("java.awt.headless", "true");  
    }  
  
    @Test  
    public void whenSetUpSuccessful_thenHeadlessIsTrue() {boolean headless = GraphicsEnvironment.isHeadless();  
        Assert.assertTrue(headless);  
    }/*  
    测试通过  
    正文上面的代码之后,单元测试不通过  
    //        System.setProperty("java.awt.headless", "true");    */  
  
    //@Test  
    //public void whenHeadlessMode_thenImagesWork() throws IOException {  
  
    //    boolean result = false;  
    //    try (InputStream inStream = HandlessTest.class.getResourceAsStream(IN_FILE);  
    //         FileOutputStream outStream = new FileOutputStream(OUT_FILE)) {//        BufferedImage inputImage = ImageIO.read(inStream);  
    //        result = ImageIO.write(inputImage, FORMAT, outStream);  
    //   }  
    //    Assert.assertTrue(result);  
    //}  
  
//    @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);  
    }  
  
    @Test  
    public void whenHeadlessmode_thenFrameThrowsHeadlessException() {Frame frame = new Frame();  
        frame.setVisible(true);  
        frame.setSize(120, 120);  
    }/*  
    在开关 Headless 模式后会有不同的后果  
    开启:通过  
    敞开  
    ava.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)   at java.awt.Frame.<init>(Frame.java:385)  
    */  
  
  
    @Test  
    public void FlexibleApp() {if (GraphicsEnvironment.isHeadless()) {System.out.println("Hello World");  
        } else {JOptionPane.showMessageDialog(null, "showMessageDialog Hello World");  
        }  
    }  
  
  
  
}

参考资料

https://www.jianshu.com/p/7248b3ff5ca7

https://www.baeldung.com/java-headless-mode](https://www.baeldung.com/java…](https://www.baeldung.com/java…))

正文完
 0