Tips のバックアップの現在との差分(No.3)
TITLE:Java Tips
Posted by aterai at 2011-01-25
- title: Java Tips author: aterai keywords: [Java, install, JAVA_HOME] description: JDKのインストール、Java Swingのデバッグ方法、環境変数で実行するjava.exeを切り替えるバッチファイルなどのメモ pubdate: 2011-01-25
-
- Java Tips
- 概要
- Ubuntu に、oracle-java8 をインストール
- Swing debug agent
- Javadoc 翻訳
- JRuby
- Swing debug agent
- -gオプションを使用してコンパイル
- 「Java Swing Hacks」本のレビュー
- Java その他
- その他
- Java メモ
- 環境変数
- コメント
- コマンドプロンプトからデフォルトのロケールを変更
- コード整形
- FileInputStream / FileOutputStream でメモリリーク
- 偶数・奇数の判断
- 正の数と負の数を反転
- Objects.compare(...)
- 無名匿名クラスとラムダ式の中でのthisキーワード
- Launch Single-File Source-Code Programs
- コメント
Java Tips
- Java Tips
- 概要
- Ubuntu に、oracle-java8 をインストール
- Swing debug agent
- Javadoc 翻訳
- JRuby
- Swing debug agent
- -gオプションを使用してコンパイル
- 「Java Swing Hacks」本のレビュー
- Java その他
- その他
- Java メモ
- 環境変数
- コメント
- コマンドプロンプトからデフォルトのロケールを変更
- コード整形
- FileInputStream / FileOutputStream でメモリリーク
- 偶数・奇数の判断
- 正の数と負の数を反転
- Objects.compare(...)
- 無名匿名クラスとラムダ式の中でのthisキーワード
- Launch Single-File Source-Code Programs
- コメント
概要
JDK
のインストール、Java Swing
のデバッグ方法、環境変数で実行するjava.exe
を切り替えるバッチファイルなどのメモの一覧です。
概要
Java のデバッグ(Swing)、Java用のバッチファイル、API-doc 翻訳などに関するメモをまとめています。Ubuntu に、oracle-java8 をインストール
-
apt-get install
でインストール
Swing debug agent
- Swingコンポーネントの再描画をJXLayerのDebugPainterを使ってデバッグ
- JXLayer のDebugPainter を使ってコンポーネントの再描画を可視化する javaagent を作成してデバッグを行います。
sudo add-apt-repository ppa:webupd8team/java sudo apt-get update sudo apt-get install oracle-java8-installer sudo update-alternatives --config javac
- JXLayer のDebugPainter を使ってコンポーネントの再描画を可視化する javaagent を作成してデバッグを行います。
- SwingアプリケーションのLookAndFeelを外部から切り替える
- SwingアプリケーションのLookAndFeelを agent を使って外部から切り替えてデバッグします。
-
tar.gz
をダウンロードしてインストール- Java SE Downloadsから、
jdk-8uxx-linux-xxxx.tar.gz
をダウンロード
- Java SE Downloadsから、
Javadoc 翻訳
Javadoc- Javadoc/Japanese
- 日本語訳で修正した方が良さそうなもの。
- Javadoc/Nitpick
- 翻訳元から修正した方が良さそうなもの。
- Javadoc/Typo
- Typo、変換ミスなど。
sudo tar zxvf jdk-8u66-linux-i586.tar.gz -C /usr/lib/jvm
- Typo、変換ミスなど。
JRuby
- JRuby+Swing - てんぷらメモ@はてな
export JAVA_HOME=/usr/lib/jvm/jdk1.8.0_66 export PATH=$PATH:$JAVA_HOME/bin
- -
- JRuby One-Liner で、UIManagerのDefaults.keySetを一覧表示する
> jruby -rjava -e "javax.swing.UIManager.lookAndFeelDefaults.keySet.each{|o| p o}"
Swing debug agent
- Swingコンポーネントの再描画をJXLayerのDebugPainterを使ってデバッグ
-
JXLayer
のDebugPainter
を使ってコンポーネントの再描画を可視化するjavaagent
を作成してデバッグを実行
-
- SwingアプリケーションのLookAndFeelを外部から切り替える
-
Swing
アプリケーションのLookAndFeel
をagent
を使って外部から切り替えてデバッグを実行
-
- -
> chcp 現在のコード ページ: 932
-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
以下のソースをコピーし、以下のようなバッチを実行#spanend #spanadd @echo off #spanend #spanadd setlocal #spanend #spanadd rem set RT_JAR=%JAVA_HOME%\jre\lib\rt.jar #spanend #spanadd set RT_JAR=rt.jar #spanend #spanadd dir /B /S /X src\*.java > filelist.txt #spanend #spanadd "%JAVA_HOME%\bin\javac" -g -classpath "%RT_JAR%" -sourcepath src -d debug @filelist.txt > log.txt 2>&1 #spanend #spanadd "%JAVA_HOME%\bin\jar" cf0 rt_debug.jar debug/* #spanend #spanadd
- 生成された
rt_debug.jar
を、%JAVA_HOME%\lib\endorsed
(なければ管理者になって作成)にコピー- Java推奨標準優先メカニズム
- 「この機能は非推奨であり、今後のリリースで削除される予定です。」、
JDK 9
では使用できない?
> jruby -J-Dfile.encoding=UTF-8 -rjava -e 'p java.net.URLEncoder.encode("日本語","UTF-8")' > jruby -J-Dfile.encoding=UTF-8 -rjava -e "puts java.net.URLEncoder.encode('日本語','UTF-8')" > jruby -J-Dfile.encoding=UTF-8 -rjava -e 'puts java.net.URLEncoder.encode(""日本語"",""UTF-8"")' > jruby --1.9 -U -rjava -e 'puts java.net.URLEncoder.encode("日本語","UTF-8")' > jruby -J-Dfile.encoding=UTF-8 -ruri -e 'puts URI.encode("日本語")' %E6%97%A5%E6%9C%AC%E8%AA%9E
> jruby --1.9 -rjava -e 'puts java.net.URLEncoder.encode("日本語","MS932")' > jruby --1.9 -ruri -e 'puts URI.encode_www_form_component("日本語")' %93%FA%96%7B%8C%EA
- JRuby + SWT のサンプル
「Java Swing Hacks」本のレビュー
Java その他
その他
- 環境変数JAVA_HOMEを変更して使用するJDKを切り替える
- 環境変数 JAVA_HOME を変更するバッチファイルを作成して、コマンドプロンプトで使用するJDKを切り替えます。
- 環境変数
JAVA_HOME
を変更するバッチファイルを作成して、コマンドプロンプトで使用するJDK
を切り替える
- Rhinoでgoogle-prettify.jsを実行する
- Rhinoでgoogle-prettify.jsを実行し、ソースコードをハイライトされたHtml(google sites用)に変換します。
- Java API Doc の「日本語、英語」をブックマークレットで切り替える?
- JavaのAPIドキュメントをブックマークレットを使って、日本語と英語で切り替えます。
-
Rhino
でgoogle-prettify.js
を実行し、ソースコードをハイライトされたHtml
(google sites
用)に変換する
- JNIでJFrameのHWNDを取得
- JNI(Java Native Interface) で JFrame(SunAwtFrame) の HWND(ウィンドウハンドル) を取得します。
-
JNI
(Java Native Interface
)でJFrame
(SunAwtFrame
)のHWND
(ウィンドウハンドル)を取得する
- Java API Doc の「日本語、英語」をブックマークレットで切り替える
Java メモ
環境変数
環境変数
- 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
のソースコードのインデントは、エディタでは4space
、Web
サイトにソースコードを表示する場合は2space
にしているので、xyzzy
のfilter-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
で変換すると、余計な}
が追加される?
#spanend
#spanadd
class Hoge
#spanend
#spanadd
{
#spanend
public static void main(String[] args)
{
System.out.println("aaaaaaa");
}
#spanadd
}
#spanend
#spanadd
- Artistic Style / Bugs / #305 Last character always repeated in output when reading from stdin
-
次バージョンで修正される模様修正済み
-
FileInputStream / FileOutputStream でメモリリーク
- 恐怖の JVM 大量メモリ消費!メモリリークの謎を追え!! - Cybozu Inside Out | サイボウズエンジニアのブログ
- JDK-8080225 FileInputStream cleanup should be improved. - Java Bug System
- FileInputStream / FileOutputStream Considered Harmful | CloudBees
- via: Inspired by Actual Events: Java Finalizer and Java File Input/Output Streams
-
FileInputStream
やFileOutputStream
は、finalize()
メソッドをオーバーライドしている(FinalReference
に登録されてしまう)のでclose()
メソッドを呼んだ後でもフルGC
が発生するまでメモリ上に残り続ける -
Files.newInputStream(...)
やFiles.newOutputStream(...)
に置き換える必要がある
- FileInputStream / FileOutputStream Considered Harmful : java
-
Files.newInputStream(...)
(ChannelInputStream
?)はskip()
がすこし遅いらしい?
-
-
ClassLoader#getResourceAsStream(...)
は?
偶数・奇数の判断
#spanend
#spanadd
public class EvenOddTest {
#spanend
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);
}
}
}
#spanadd
}
#spanend
#spanadd
正の数と負の数を反転
- How do you Invert signed numbers? | Oracle Community
- 15.15.4. Unary Minus Operator - / Chapter 15. Expressions
#spanend
#spanadd
public class InvertSignedNumbersTest {
#spanend
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);
}
#spanadd
}
#spanend
#spanadd
Objects.compare(...)
#spanend
/**
* 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);
}
#spanadd
- java - What is the purpose of the Objects.compare() method? - Stack Overflow
- 確かに
Objects.compare(...)
の使いどころが分からない -
TableSorter.java
の以下のようなコードが短くなるか?と考えたが、#spanend #spanadd //@see https://docs.oracle.com/javase/tutorial/uiswing/examples/components/TableSorterDemoProject/src/components/TableSorter.java #spanend #spanadd public int compareTo(Object o) { #spanend int row1 = modelIndex; int row2 = ((Row) o).modelIndex; #spanadd #spanend 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); #spanadd #spanend 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; #spanadd } #spanend #spanadd
- 確かに
- 以下のように
Objects.compare(...)
を使用すると、テーブルモデルの値にnull
が存在する場合、ソートでNullPointerException
が発生する - Java Comparatorメモ(Hishidama's Java Comparator Memo)を参考に、
Comparator.nullsFirst(comparator)
と合わせて使用すれば、NullPointerException
は発生しない
#spanend
#spanadd
//@see https://docs.oracle.com/javase/tutorial/uiswing/examples/components/TableSorterDemoProject/src/components/TableSorter.java
#spanend
#spanadd
public int compareTo(Object o) {
#spanend
int row1 = modelIndex;
int row2 = ((Row) o).modelIndex;
#spanadd
#spanend
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);
#spanadd
#spanend
@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;
#spanadd
}
#spanend
#spanadd
無名匿名クラスとラムダ式の中でのthisキーワード
- 15.27.2. Lambda Body - Chapter 15. Expressions
- Javaラムダ式メモ(Hishidama's Java8 Lambda Expression Memo)
- 単純に無名匿名クラスをラムダ式に置き換えると、「
static
でないメソッドgetClass()
をstatic
コンテキストから参照することはできません」とコンパイルエラーになる場合がある#spanend #spanadd MainPanel.java:43: error: non-static method getClass() cannot be referenced from a static context #spanend splashScreen.getContentPane().add(new JLabel(new ImageIcon(getClass().getResource("splash.png")))); #spanadd
- 無名匿名クラス中の
this
キーワードは、無名匿名クラスのインスタンスを指すが、ラムダ式はラムダ式を定義したメソッドが属しているクラスのインスタンスを指すため
- 無名匿名クラス中の
-
this.getClass()
ではなく、MainPanel.class.getClass()
のようにclass
リテラルを使用して回避
#spanend
#spanadd
import java.awt.*;
#spanend
#spanadd
import java.beans.*;
#spanend
#spanadd
import javax.swing.*;
#spanend
#spanadd
#spanend
#spanadd
public final class MainPanel extends JPanel {
#spanend
private MainPanel() {
super(new BorderLayout());
try {
Thread.sleep(3000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
add(new JScrollPane(new JTree()));
setPreferredSize(new Dimension(320, 240));
}
#spanadd
#spanend
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();
#spanadd
#spanend
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.getContentPane().add(new MainPanel());
frame.pack();
frame.setLocationRelativeTo(null);
EventQueue.invokeLater(() -> frame.setVisible(true));
}
#spanadd
}
#spanend
#spanadd
#spanend
#spanadd
class Task extends SwingWorker<Void, Void> {
#spanend
@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;
}
#spanadd
}
#spanend
#spanadd
Launch Single-File Source-Code Programs
-
Java 11
では、1
つの.java
ファイルをjava
コマンドで実行可能になった - 例えば以下のようなコードを
./TreeRootVisible/src/java/example/MainPanel.java
に生成した場合、package
は考慮しなくても実行可能:
#spanend
#spanadd
package example;
#spanend
#spanadd
#spanend
#spanadd
import java.awt.*;
#spanend
#spanadd
import javax.swing.*;
#spanend
#spanadd
#spanend
#spanadd
public final class MainPanel extends JPanel {
#spanend
private MainPanel() {
super(new BorderLayout());
#spanadd
#spanend
JTree tree = new JTree();
tree.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
tree.setRootVisible(false);
#spanadd
#spanend
JCheckBox check = new JCheckBox("JTree#setRootVisible(...)");
check.addActionListener(e -> tree.setRootVisible(((JCheckBox) e.getSource()).isSelected()));
#spanadd
#spanend
add(check, BorderLayout.NORTH);
add(new JScrollPane(tree));
setPreferredSize(new Dimension(320, 240));
}
#spanadd
#spanend
public static void main(String... args) {
EventQueue.invokeLater(new Runnable() {
@Override public void run() {
createAndShowGui();
}
});
}
#spanadd
#spanend
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);
}
#spanadd
}
#spanend
#spanadd
#spanend
> sdk use java 11.0.3-amzn
> cd ./TreeRootVisible/src/java/example/
> java MainPanel.java # OK
> cd ..
> java example/MainPanel.java # OK
#spanadd
- 画像などのリソースを
.java
ファイルと同じディレクトリに配置し、ImageIcon icon = new ImageIcon(getClass().getResource("test.png"));
で参照する場合:
#spanend
> sdk use java 11.0.3-amzn
> cd ./Zoom/src/java/example/
> ls
#spanadd
MainPanel.java test.png
#spanend
> java MainPanel.java # NG
#spanadd
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
#spanend
> cd ..
> java example/MainPanel.java # OK
#spanadd