ProcessBuilder
ProcessBuilderクラスを使って、Javaプログラム起動用の簡単なランチャーを書いてみる。
import java.awt.Color; import java.awt.Font; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Properties; import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JWindow; import javax.swing.SwingUtilities; public class Launcher { private Properties properties; public Launcher(Properties p){ properties=p; } private JWindow createSplashScreen(String path) { ImageIcon img=null; try{ if(path!=null){ BufferedImage im=ImageIO.read(new File(path)); img=new ImageIcon(im); } }catch(IOException ie){ }catch(NullPointerException ie){} JLabel splashLabel; if(img!=null){ splashLabel=new JLabel(img); }else{ splashLabel=new JLabel(properties.getProperty("name")); splashLabel.setFont(new Font(Font.DIALOG,Font.BOLD,36)); } splashLabel.setOpaque(true); splashLabel.setBackground(new Color(255,255,255,0)); JWindow splash=new JWindow(new JFrame()); splash.getContentPane().add(splashLabel); splash.setBackground(new Color(255,255,255,0)); splash.setAlwaysOnTop(true); splash.pack(); splash.setLocationRelativeTo(null); return splash; } private void start(){ long delay=Long.parseLong(properties.getProperty("delay")); final JWindow splash=createSplashScreen( properties.getProperty("image")); SwingUtilities.invokeLater(new Runnable() { public void run() { splash.setVisible(true); } }); try { init(); Thread.sleep(delay); System.exit(0); } catch(InterruptedException ex) {} } private List<File> addJarList(List<File> list,String obj){ if(obj==null)return list; File f=new File(obj); if(f.exists()&&f.isDirectory()){ File[] ff=f.listFiles(); for(int i=0;i<ff.length;i++){ if(ff[i].getName().toLowerCase().endsWith("jar")){ list.add(ff[i]); } } } return list; } private void init(){ List<File> list=new ArrayList<File>(); String line=properties.getProperty("path"); String[] obj=line.split(","); for(int i=0;i<obj.length;i++){ list=addJarList(list,obj[i]); } String path="."; for(int i=0;i<list.size();i++){ File fx=list.get(i); path=path+";\""+fx.getAbsolutePath()+"\""; } try{ List<String> args=new ArrayList<String>(); args.add("java"); args.add("-cp"); args.add(path); args.add("-Xmx"+properties.getProperty("memory")+"m"); String op=properties.getProperty("option"); if(op!=null&&op.isEmpty()){ args.add(op); } args.add(properties.getProperty("exec")); ProcessBuilder pb=new ProcessBuilder(args); pb.redirectErrorStream(true); pb.start(); }catch(Exception e){ e.printStackTrace(); } } public static void main(String[] args){ Properties prop = new Properties(); try{ prop.loadFromXML(new FileInputStream("properties.xml")); Launcher app=new Launcher(prop); app.start(); }catch(FileNotFoundException fe){ fe.printStackTrace(); }catch(IOException ie){ ie.printStackTrace(); } } }
■プロパティファイル(properties.xml)
以下のようなプロパティファイルを作成する。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> <comment>TmFlow2D ver.0.1</comment> <entry key="name">TmFlow2D</entry> <entry key="image">./splash.png</entry> <entry key="delay">3000</entry> <entry key="path">lib,bin</entry> <entry key="memory">256</entry> <entry key="option">-Dawt.useSystemAAFontSettings=on</entry> <entry key="exec">jp.t.matsuoka.tmflow2d.gui.TmFlow2dApp</entry> </properties>
なお、
- name=プログラム名
- image=スプラッシュ画像の相対パス
- delay=スプラッシュ画像の表示時間
- path=クラスパスを通すJarファイルがあるフォルダの相対パス(カンマで複数指定)
- memory=JVMの最大メモリ
- option=その他のJVMオプション
- exec=起動するクラス
■結果
executable-jarにしたLauncherクラスを起動すると、properties.xmlを読み込み、スプラッシュウィンドウを表示する。その後、pathに設定したフォルダ内のJarファイルにクラスパスを通し、別プロセスで目的のクラスを起動する。
クラスパスとかの設定が不要なので、以外に便利だったりする。