概要

JDKのインストール、Java Swingのデバッグ方法、環境変数で実行するjava.exeを切り替えるバッチファイルなどのメモの一覧です。

Ubuntu に、oracle-java8 をインストール

sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update
sudo apt-get install oracle-java8-installer
sudo update-alternatives --config javac
  • tar.gzをダウンロードしてインストール
sudo tar zxvf jdk-8u66-linux-i586.tar.gz -C /usr/lib/jvm
export JAVA_HOME=/usr/lib/jvm/jdk1.8.0_66
export PATH=$PATH:$JAVA_HOME/bin

Swing debug agent

-gオプションを使用してコンパイル

  • NetBeansでソースにブレークポイントを設定し、Swingコンポーネントのソースにステップインすると、「変数の情報を使用できません。ソースは -gオプションを使用せずにコンパイルされています」と表示され、値は不明となる
  • javac -gオプション
    -g ローカル変数を含むすべてのデバッグ情報を生成します。デフォルトでは、行番号およびソース・ファイル情報だけが生成されます。
  • java - debug jdk source can't watch variable what it is - Stack Overflowを参考に、%JAVA_HOME%/src.zip/javax/swing以下のソースをコピーし、以下のようなバッチを実行
    @echo off
    setlocal
    rem set RT_JAR=%JAVA_HOME%\jre\lib\rt.jar
    set RT_JAR=rt.jar
    dir /B /S /X src\*.java > filelist.txt
    "%JAVA_HOME%\bin\javac" -g -classpath "%RT_JAR%" -sourcepath src -d debug @filelist.txt > log.txt 2>&1
    "%JAVA_HOME%\bin\jar" cf0 rt_debug.jar debug/*
    
  • 生成されたrt_debug.jarを、%JAVA_HOME%\lib\endorsed(なければ管理者になって作成)にコピー

その他

環境変数

  • http://cr.openjdk.java.net/~gbenson/zero-08/raw_files/new/hotspot/src/share/vm/utilities/vmError.cpp
    // List of environment variables that should be reported in error log file.
    const char *env_list[] = {
      // All platforms
      "JAVA_HOME", "JRE_HOME", "JAVA_TOOL_OPTIONS", "_JAVA_OPTIONS", "CLASSPATH",
      "JAVA_COMPILER", "PATH", "USERNAME",
    
      // Env variables that are defined on Solaris/Linux
      "LD_LIBRARY_PATH", "LD_PRELOAD", "SHELL", "DISPLAY",
      "HOSTTYPE", "OSTYPE", "ARCH", "MACHTYPE",
    
      // defined on Linux
      "LD_ASSUME_KERNEL", "_JAVA_SR_SIGNUM",
    
      // defined on Windows
      "OS", "PROCESSOR_IDENTIFIER", "_ALT_JAVA_HOME_DIR",
    
      (const char *)0
    };
    

コマンドプロンプトからデフォルトのロケールを変更

> javac -J-Duser.language=en Test.java
> java -Duser.language=en Test
  • 国際化についての FAQ
    アプリケーションの外部からデフォルトのロケールを設定できますか。
    
    使用している Java プラットフォームの実装によって異なります。通常、初期のデフォルトロケールは、ホストオペレーティングシステムのロケールによって決まります。Sun の JRE のバージョン 1.4 以降では、コマンド行から user.language、user.country、および user.variant の各システムプロパティを設定することで、初期のデフォルトロケールを変更できます。たとえば、初期のデフォルトロケールとして Locale("th", "TH", "TH") を選択するには、次のコマンドを使用します。
    java -Duser.language=th -Duser.country=TH -Duser.variant=TH MainClass
    
    この機能を使用できない実行環境もあるため、この機能はテスト目的だけに使用してください。

コード整形

個人的に、Javaのソースコードのインデントは、エディタでは4spaceWebサイトにソースコードを表示する場合は2spaceにしているので、xyzzyfilter-buffer(C-x #)でastyleを呼び出して以下のように整形。

astyle --style=java --mode=java --indent=spaces=2

コマンドラインなどから、ファイルを指定する場合も同様。

> astyle --style=java --mode=java --indent=spaces=4 MainPanel.java

Markdown形式のStack Overflowなどにソースコードを貼り付ける場合は、以下のようにして、行頭にタブ(またはスペース4つ)を追加。

astyle --style=java --mode=java --indent=spaces=2 < Hoge.java | sed -e "s/^\(.*\)$/\t\1/" > /dev/clipboard
astyle --style=java --mode=java --indent=spaces=2 | sed -e "s/^\(.*\)$/\t\1/"
astyle --style=java --mode=java --indent=spaces=2 | sed -e "s/\A\(.*\)\z/    \1/"

astyle

astyle --style=java --mode=java --indent=spaces=4 --pad-oper --pad-header --unpad-paren

キャストの後にスペースを入れる方法は?

int h = (int)(.5 + baseline / height);
//(int)の後に空白を入れたい...
int h = (int) (.5 + baseline / height);

asyle 2.04

$ astyle --version
Artistic Style Version 2.04
  • 以下の様なソースコード(最後の}の直後にEOF)をastyleで変換すると、余計な}が追加される?
class Hoge
{
    public static void main(String[] args)
    {
        System.out.println("aaaaaaa");
    }
}

FileInputStream / FileOutputStream でメモリリーク

偶数・奇数の判断

public class EvenOddTest {
  public static void main(String... args) {
    for (int i = 0; i < 5; i++) {
      if (i % 2 == 0) {
        System.out.format("%d is even%n", i);
      } else {
        System.out.format("%d is odd%n", i);
      }
      if ((i & 1) == 0) { // ビット演算子の & は、== より優先順位が低いので(i & 1)と囲む必要がある
        System.out.format("%d is even%n", i);
      } else {
        System.out.format("%d is odd%n", i);
      }
    }
  }
}

正の数と負の数を反転

public class InvertSignedNumbersTest {
  private static void print(int i) {
    System.out.println(i);
    System.out.format(" :%d\n", -i);
    System.out.format(" :%d\n", ~i + 1);
    System.out.format(" :%d\n", (i > 0 ? -1 : 1) * Math.abs(i));
    System.out.format(" :%d\n", ~--i);
  }
  public static void main(String... args) {
    print(256);
    print(-256);
    print(0);
    print(-0);
    print(Integer.MAX_VALUE);
    print(Integer.MIN_VALUE + 1);
    print(Integer.MIN_VALUE);
  }
}

Objects.compare(...)

    /**
     * Returns 0 if the arguments are identical and {@code
     * c.compare(a, b)} otherwise.
     * Consequently, if both arguments are {@code null} 0
     * is returned.
     *
     * <p>Note that if one of the arguments is {@code null}, a {@code
     * NullPointerException} may or may not be thrown depending on
     * what ordering policy, if any, the {@link Comparator Comparator}
     * chooses to have for {@code null} values.
     *
     * @param <T> the type of the objects being compared
     * @param a an object
     * @param b an object to be compared with {@code a}
     * @param c the {@code Comparator} to compare the first two arguments
     * @return 0 if the arguments are identical and {@code
     * c.compare(a, b)} otherwise.
     * @see Comparable
     * @see Comparator
     */
    public static <T> int compare(T a, T b, Comparator<? super T> c) {
        return (a == b) ? 0 :  c.compare(a, b);
    }
  • java - What is the purpose of the Objects.compare() method? - Stack Overflow
    • 確かにObjects.compare(...)の使いどころが分からない
    • TableSorter.javaの以下のようなコードが短くなるか?と考えたが、
      //@see https://docs.oracle.com/javase/tutorial/uiswing/examples/components/TableSorterDemoProject/src/components/TableSorter.java
      public int compareTo(Object o) {
        int row1 = modelIndex;
        int row2 = ((Row) o).modelIndex;
      
        for (Iterator it = sortingColumns.iterator(); it.hasNext();) {
          Directive directive = (Directive) it.next();
          int column = directive.column;
          Object o1 = tableModel.getValueAt(row1, column);
          Object o2 = tableModel.getValueAt(row2, column);
      
          int comparison = 0;
          // Define null less than everything, except null.
          if (o1 == null && o2 == null) {
            comparison = 0;
          } else if (o1 == null) {
            comparison = -1;
          } else if (o2 == null) {
            comparison = 1;
          } else {
            comparison = getComparator(column).compare(o1, o2);
          }
          if (comparison != 0) {
            return directive.direction == DESCENDING ? -comparison : comparison;
          }
        }
        return 0;
      }
      
  • 以下のようにObjects.compare(...)を使用すると、テーブルモデルの値にnullが存在する場合、ソートでNullPointerExceptionが発生する
  • Java Comparatorメモ(Hishidama's Java Comparator Memo)を参考に、Comparator.nullsFirst(comparator)と合わせて使用すれば、NullPointerExceptionは発生しない
//@see https://docs.oracle.com/javase/tutorial/uiswing/examples/components/TableSorterDemoProject/src/components/TableSorter.java
public int compareTo(Object o) {
  int row1 = modelIndex;
  int row2 = ((Row) o).modelIndex;

  for (Iterator it = sortingColumns.iterator(); it.hasNext();) {
    Directive directive = (Directive) it.next();
    int column = directive.column;
    Object o1 = tableModel.getValueAt(row1, column);
    Object o2 = tableModel.getValueAt(row2, column);

    @SuppressWarnings("unchecked")
    Comparator<Object> comparator = getComparator(column);
    int comparison = Objects.compare(o1, o2, comparator);
    //int comparison = Objects.compare(o1, o2, Comparator.nullsFirst(comparator));
    if (comparison != 0) {
      return directive.direction == DESCENDING ? ~comparison + 1 : comparison;
    }
  }
  return 0;
}

無名匿名クラスとラムダ式の中でのthisキーワード

import java.awt.*;
import java.beans.*;
import javax.swing.*;

public final class MainPanel extends JPanel {
  private MainPanel() {
    super(new BorderLayout());
    try {
      Thread.sleep(3000);
    } catch (InterruptedException ex) {
      ex.printStackTrace();
    }
    add(new JScrollPane(new JTree()));
    setPreferredSize(new Dimension(320, 240));
  }

  public static void main(String... args) {
    /*
    final JFrame frame = new JFrame();
    final JDialog splashScreen  = new JDialog(frame, Dialog.ModalityType.DOCUMENT_MODAL);
    final JProgressBar progress = new JProgressBar();
    EventQueue.invokeLater(new Runnable() {
        @Override public void run() {
            splashScreen.setUndecorated(true);
            splashScreen.getContentPane().add(new JLabel(new ImageIcon(getClass().getResource("splash.png"))));
            splashScreen.getContentPane().add(progress, BorderLayout.SOUTH);
            splashScreen.pack();
            splashScreen.setLocationRelativeTo(null);
            splashScreen.setVisible(true);
        }
    });
    /*/
    JFrame frame = new JFrame();
    JDialog splashScreen  = new JDialog(frame, Dialog.ModalityType.DOCUMENT_MODAL);
    JProgressBar progress = new JProgressBar();
    EventQueue.invokeLater(() -> {
      splashScreen.setUndecorated(true);
      splashScreen.getContentPane().add(new JLabel(new ImageIcon(MainPanel.class.getResource("splash.png"))));
      //NG: splashScreen.getContentPane().add(new JLabel(new ImageIcon(getClass().getResource("splash.png"))));
      splashScreen.getContentPane().add(progress, BorderLayout.SOUTH);
      splashScreen.pack();
      splashScreen.setLocationRelativeTo(null);
      splashScreen.setVisible(true);
    });
    //*/
    SwingWorker<Void, Void> worker = new Task() {
      @Override public void done() {
        splashScreen.dispose();
      }
    };
    worker.addPropertyChangeListener(e -> {
      if ("progress".equals(e.getPropertyName())) {
        progress.setValue((Integer) e.getNewValue());
      }
    });
    worker.execute();

    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frame.getContentPane().add(new MainPanel());
    frame.pack();
    frame.setLocationRelativeTo(null);
    EventQueue.invokeLater(() -> frame.setVisible(true));
  }
}

class Task extends SwingWorker<Void, Void> {
  @Override public Void doInBackground() {
    int current = 0;
    int lengthOfTask = 120;
    while (current < lengthOfTask && !isCancelled()) {
      try {
        Thread.sleep(50);
      } catch (InterruptedException ie) {
        ie.printStackTrace();
        return null;
      }
      setProgress(100 * current++ / lengthOfTask);
    }
    return null;
  }
}

Launch Single-File Source-Code Programs

  • Java 11では、1つの.javaファイルをjavaコマンドで実行可能になった
  • 例えば以下のようなコードを./TreeRootVisible/src/java/example/MainPanel.javaに生成した場合、packageは考慮しなくても実行可能:
package example;

import java.awt.*;
import javax.swing.*;

public final class MainPanel extends JPanel {
  private MainPanel() {
    super(new BorderLayout());

    JTree tree = new JTree();
    tree.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
    tree.setRootVisible(false);

    JCheckBox check = new JCheckBox("JTree#setRootVisible(...)");
    check.addActionListener(e -> tree.setRootVisible(((JCheckBox) e.getSource()).isSelected()));

    add(check, BorderLayout.NORTH);
    add(new JScrollPane(tree));
    setPreferredSize(new Dimension(320, 240));
  }

  public static void main(String... args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        createAndShowGui();
      }
    });
  }

  public static void createAndShowGui() {
    try {
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
      ex.printStackTrace();
      Toolkit.getDefaultToolkit().beep();
    }
    JFrame frame = new JFrame("@title@");
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frame.getContentPane().add(new MainPanel());
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}
> sdk use java 11.0.3-amzn
> cd ./TreeRootVisible/src/java/example/
> java MainPanel.java # OK
> cd ..
> java example/MainPanel.java # OK
  • 画像などのリソースを.javaファイルと同じディレクトリに配置し、ImageIcon icon = new ImageIcon(getClass().getResource("test.png"));で参照する場合:
> sdk use java 11.0.3-amzn
> cd ./Zoom/src/java/example/
> ls
MainPanel.java  test.png
> java MainPanel.java # NG
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
> cd ..
> java example/MainPanel.java # OK

コメント

}}