Rust製JVMを
作成した話
ついでにWasmでブラウザで動かす
-
名前: r-chaser53
-
GitHub: https://github.com/rchaser53
-
Twitter: https://twitter.com/rChaser53
-
所属: LINE株式会社
-
何やってる人?
-
言語開発とか好きな人(歴は1.5年くらい)
-
rustfmtのお手伝いを今年はしてます
-
誰?
-
仕様書を元にした開発を一回やってみたい
-
Javaの仕様書は結構良いらしい(真偽不明)
-
Stack Machineの学習ついでにやろう
-
インスタンス、配列など色々参考にしよう
背景
というわけで
なんか流行ってるし、やってみよう
ついでにブラウザで動かそう
成果物
-
ローカルでのRust製JVMの作成(※1)
-
ブラウザ上でWasmとして実行
今回やったこと
-
実装すること
-
実際に覗いてみる
-
ビルトインのクラスについて
1. ローカルでのRust製JVMの作成
何をすれば良いの?
実装すること
-
classファイルを引数にした実行可能ファイルを作成する
- classファイルは本当に仕様書の通りのフォーマット
-
シンプルにそれを解釈して実行できるようにすれば良い
本当にそれだけで良いの?
実際に覗いてみる
-
0xEDというバイナリ編集ソフトを使う
- シンプルなHelloWorldを出力するClassファイルを作成
- ちょっと先端だけ本当にmagicなのか確認してみる
- magicは「0xCAFEBABE」という数値
// これをjavacで実行してTest.classを作る
public class Test {
public static void main(String[] args) {
System.out.println("HelloWorld");
}
}
HelloWorld出力するコード
本当にそれだけで良いの?②
-
先端はmagic、「0xCAFEBABE」のはず…
実際に覗いてみる
本当にそれだけで良いの?③
-
先端はmagic、「0xCAFEBABE」のはず…
本当にフォーマット通り
実際に覗いてみる
話はそんなに簡単に進まない
ビルトインのクラスについて
-
普段使っているビルトインのクラスは仕様書には存在しない
- System.outも当然なくprintlnが実行できない
- HelloWorldができない!!
話はそんなに簡単に進まない②
ビルトインのクラスについて
-
JDKの方にソースコードは存在する
- またjavapを用いても確認できる
- javapはJava クラスファイル逆アセンブラの略。便利
- よし手段は見つかった
HelloWorldが遠ざかる…
ビルトインのクラスについて
-
実際にはSystem.outではなくjava/io/PrintStreamになる
- 実装量が非常に多い。必要箇所だけでも厳しい
- 本気でリビルドしない限り代替手段を取った方が無難
rchaser53noMacBook-Pro:rj rchaser53$ javap -v java/io/PrintStream
Classfile jar:file:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/rt.jar!/java/io/PrintStream.class
Last modified 2017/07/21; size 9048 bytes
MD5 checksum f62b2b102171bb9cd2cefa5efcf0e487
Compiled from "PrintStream.java"
public class java.io.PrintStream extends java.io.FilterOutputStream implements java.lang.Appendable,java.io.Closeable
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Class #165 // java/lang/NullPointerException
#2 = Methodref #1.#166 // java/lang/NullPointerException."<init>":(Ljava/lang/String;)V
#3 = String #167 // charsetName
#4 = Methodref #40.#168 // java/io/PrintStream.requireNonNull:(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;
#5 = Methodref #169.#170 // java/nio/charset/Charset.forName:(Ljava/lang/String;)Ljava/nio/charset/Charset;
#6 = Class #171 // java/nio/charset/IllegalCharsetNameException
#7 = Class #172 // java/nio/charset/UnsupportedCharsetException
#8 = Class #173 // java/io/UnsupportedEncodingException
#9 = Methodref #8.#166 // java/io/UnsupportedEncodingException."<init>":(Ljava/lang/String;)V
#10 = Methodref #87.#174 // java/io/FilterOutputStream."<init>":(Ljava/io/OutputStream;)V
#11 = Fieldref #40.#175 // java/io/PrintStream.trouble:Z
#12 = Fieldref #40.#176 // java/io/PrintStream.closing:Z
#13 = Fieldref #40.#177 // java/io/PrintStream.autoFlush:Z
#14 = Class #178 // java/io/OutputStreamWriter
#15 = Methodref #14.#174 // java/io/OutputStreamWriter."<init>":(Ljava/io/OutputStream;)V
#16 = Fieldref #40.#179 // java/io/PrintStream.charOut:Ljava/io/OutputStreamWriter;
#17 = Class #180 // java/io/BufferedWriter
#18 = Methodref #17.#181 // java/io/BufferedWriter."<init>":(Ljava/io/Writer;)V
#19 = Fieldref #40.#182 // java/io/PrintStream.textOut:Ljava/io/BufferedWriter;
#20 = Methodref #14.#183 // java/io/OutputStreamWriter."<init>":(Ljava/io/OutputStream;Ljava/nio/charset/Charset;)V
#21 = Methodref #40.#184 // java/io/PrintStream."<init>":(ZLjava/io/OutputStream;Ljava/nio/charset/Charset;)V
#22 = Methodref #40.#185 // java/io/PrintStream."<init>":(Ljava/io/OutputStream;Z)V
#23 = String #186 // Null output stream
#24 = Class #187 // java/io/OutputStream
#25 = Methodref #40.#188 // java/io/PrintStream."<init>":(ZLjava/io/OutputStream;)V
#26 = Methodref #40.#189 // java/io/PrintStream.toCharset:(Ljava/lang/String;)Ljava/nio/charset/Charset;
#27 = Class #190 // java/io/FileOutputStream
#28 = Methodref #27.#166 // java/io/FileOutputStream."<init>":(Ljava/lang/String;)V
#29 = Methodref #40.#191 // java/io/PrintStream."<init>":(ZLjava/nio/charset/Charset;Ljava/io/OutputStream;)V
#30 = Methodref #27.#192 // java/io/FileOutputStream."<init>":(Ljava/io/File;)V
#31 = Fieldref #40.#193 // java/io/PrintStream.out:Ljava/io/OutputStream;
#32 = Class #194 // java/io/IOException
#33 = String #195 // Stream closed
#34 = Methodref #32.#166 // java/io/IOException."<init>":(Ljava/lang/String;)V
#35 = Methodref #40.#196 // java/io/PrintStream.ensureOpen:()V
#36 = Methodref #24.#197 // java/io/OutputStream.flush:()V
#37 = Methodref #17.#198 // java/io/BufferedWriter.close:()V
#38 = Methodref #24.#198 // java/io/OutputStream.close:()V
#39 = Methodref #40.#197 // java/io/PrintStream.flush:()V
#40 = Class #199 // java/io/PrintStream
#41 = Methodref #40.#200 // java/io/PrintStream.checkError:()Z
#42 = Methodref #24.#201 // java/io/OutputStream.write:(I)V
#43 = Class #202 // java/io/InterruptedIOException
#44 = Methodref #203.#204 // java/lang/Thread.currentThread:()Ljava/lang/Thread;
#45 = Methodref #203.#205 // java/lang/Thread.interrupt:()V
#46 = Methodref #24.#206 // java/io/OutputStream.write:([BII)V
#47 = Methodref #17.#207 // java/io/BufferedWriter.write:([C)V
#48 = Methodref #17.#208 // java/io/BufferedWriter.flushBuffer:()V
#49 = Methodref #14.#208 // java/io/OutputStreamWriter.flushBuffer:()V
#50 = Methodref #17.#209 // java/io/BufferedWriter.write:(Ljava/lang/String;)V
#51 = Methodref #210.#211 // java/lang/String.indexOf:(I)I
#52 = Methodref #17.#212 // java/io/BufferedWriter.newLine:()V
#53 = String #213 // true
#54 = String #214 // false
#55 = Methodref #40.#209 // java/io/PrintStream.write:(Ljava/lang/String;)V
#56 = Methodref #210.#215 // java/lang/String.valueOf:(C)Ljava/lang/String;
#57 = Methodref #210.#216 // java/lang/String.valueOf:(I)Ljava/lang/String;
#58 = Methodref #210.#217 // java/lang/String.valueOf:(J)Ljava/lang/String;
#59 = Methodref #210.#218 // java/lang/String.valueOf:(F)Ljava/lang/String;
#60 = Methodref #210.#219 // java/lang/String.valueOf:(D)Ljava/lang/String;
#61 = Methodref #40.#207 // java/io/PrintStream.write:([C)V
#62 = String #220 // null
#63 = Methodref #210.#221 // java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
#64 = Methodref #40.#212 // java/io/PrintStream.newLine:()V
#65 = Methodref #40.#222 // java/io/PrintStream.print:(Z)V
#66 = Methodref #40.#223 // java/io/PrintStream.print:(C)V
#67 = Methodref #40.#224 // java/io/PrintStream.print:(I)V
#68 = Methodref #40.#225 // java/io/PrintStream.print:(J)V
#69 = Methodref #40.#226 // java/io/PrintStream.print:(F)V
#70 = Methodref #40.#227 // java/io/PrintStream.print:(D)V
#71 = Methodref #40.#228 // java/io/PrintStream.print:([C)V
#72 = Methodref #40.#229 // java/io/PrintStream.print:(Ljava/lang/String;)V
#73 = Methodref #40.#230 // java/io/PrintStream.format:(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream;
#74 = Methodref #40.#231 // java/io/PrintStream.format:(Ljava/util/Locale;Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream;
#75 = Fieldref #40.#232 // java/io/PrintStream.formatter:Ljava/util/Formatter;
#76 = Methodref #78.#233 // java/util/Formatter.locale:()Ljava/util/Locale;
#77 = Methodref #234.#235 // java/util/Locale.getDefault:()Ljava/util/Locale;
#78 = Class #236 // java/util/Formatter
#79 = Methodref #78.#237 // java/util/Formatter."<init>":(Ljava/lang/Appendable;)V
#80 = Methodref #78.#238 // java/util/Formatter.format:(Ljava/util/Locale;Ljava/lang/String;[Ljava/lang/Object;)Ljava/util/Formatter;
#81 = Methodref #78.#239 // java/util/Formatter."<init>":(Ljava/lang/Appendable;Ljava/util/Locale;)V
#82 = InterfaceMethodref #240.#241 // java/lang/CharSequence.toString:()Ljava/lang/String;
#83 = InterfaceMethodref #240.#242 // java/lang/CharSequence.subSequence:(II)Ljava/lang/CharSequence;
#84 = Methodref #40.#243 // java/io/PrintStream.append:(C)Ljava/io/PrintStream;
#85 = Methodref #40.#244 // java/io/PrintStream.append:(Ljava/lang/CharSequence;II)Ljava/io/PrintStream;
#86 = Methodref #40.#245 // java/io/PrintStream.append:(Ljava/lang/CharSequence;)Ljava/io/PrintStream;
#87 = Class #246 // java/io/FilterOutputStream
#88 = Class #247 // java/lang/Appendable
#89 = Class #248 // java/io/Closeable
#90 = Utf8 autoFlush
#91 = Utf8 Z
#92 = Utf8 trouble
#93 = Utf8 formatter
#94 = Utf8 Ljava/util/Formatter;
#95 = Utf8 textOut
#96 = Utf8 Ljava/io/BufferedWriter;
#97 = Utf8 charOut
#98 = Utf8 Ljava/io/OutputStreamWriter;
#99 = Utf8 closing
#100 = Utf8 requireNonNull
#101 = Utf8 (Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;
#102 = Utf8 Code
#103 = Utf8 LineNumberTable
#104 = Utf8 StackMapTable
#105 = Utf8 Signature
#106 = Utf8 <T:Ljava/lang/Object;>(TT;Ljava/lang/String;)TT;
#107 = Utf8 toCharset
#108 = Utf8 (Ljava/lang/String;)Ljava/nio/charset/Charset;
#109 = Class #249 // java/lang/IllegalArgumentException
#110 = Utf8 Exceptions
#111 = Utf8 <init>
#112 = Utf8 (ZLjava/io/OutputStream;)V
#113 = Utf8 (ZLjava/io/OutputStream;Ljava/nio/charset/Charset;)V
#114 = Utf8 (ZLjava/nio/charset/Charset;Ljava/io/OutputStream;)V
#115 = Utf8 (Ljava/io/OutputStream;)V
#116 = Utf8 (Ljava/io/OutputStream;Z)V
#117 = Utf8 (Ljava/io/OutputStream;ZLjava/lang/String;)V
#118 = Utf8 (Ljava/lang/String;)V
#119 = Class #250 // java/io/FileNotFoundException
#120 = Utf8 (Ljava/lang/String;Ljava/lang/String;)V
#121 = Utf8 (Ljava/io/File;)V
#122 = Utf8 (Ljava/io/File;Ljava/lang/String;)V
#123 = Utf8 ensureOpen
#124 = Utf8 ()V
#125 = Utf8 flush
#126 = Class #199 // java/io/PrintStream
#127 = Class #251 // java/lang/Object
#128 = Class #194 // java/io/IOException
#129 = Class #252 // java/lang/Throwable
#130 = Utf8 close
#131 = Utf8 checkError
#132 = Utf8 ()Z
#133 = Utf8 setError
#134 = Utf8 clearError
#135 = Utf8 write
#136 = Utf8 (I)V
#137 = Class #202 // java/io/InterruptedIOException
#138 = Utf8 ([BII)V
#139 = Utf8 ([C)V
#140 = Utf8 newLine
#141 = Utf8 print
#142 = Utf8 (Z)V
#143 = Class #253 // java/lang/String
#144 = Utf8 (C)V
#145 = Utf8 (J)V
#146 = Utf8 (F)V
#147 = Utf8 (D)V
#148 = Utf8 (Ljava/lang/Object;)V
#149 = Utf8 println
#150 = Class #254 // "[C"
#151 = Utf8 printf
#152 = Utf8 (Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream;
#153 = Utf8 (Ljava/util/Locale;Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream;
#154 = Utf8 format
#155 = Utf8 append
#156 = Utf8 (Ljava/lang/CharSequence;)Ljava/io/PrintStream;
#157 = Utf8 (Ljava/lang/CharSequence;II)Ljava/io/PrintStream;
#158 = Class #255 // java/lang/CharSequence
#159 = Utf8 (C)Ljava/io/PrintStream;
#160 = Utf8 (C)Ljava/lang/Appendable;
#161 = Utf8 (Ljava/lang/CharSequence;II)Ljava/lang/Appendable;
#162 = Utf8 (Ljava/lang/CharSequence;)Ljava/lang/Appendable;
#163 = Utf8 SourceFile
#164 = Utf8 PrintStream.java
#165 = Utf8 java/lang/NullPointerException
#166 = NameAndType #111:#118 // "<init>":(Ljava/lang/String;)V
#167 = Utf8 charsetName
#168 = NameAndType #100:#101 // requireNonNull:(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;
#169 = Class #256 // java/nio/charset/Charset
#170 = NameAndType #257:#108 // forName:(Ljava/lang/String;)Ljava/nio/charset/Charset;
#171 = Utf8 java/nio/charset/IllegalCharsetNameException
#172 = Utf8 java/nio/charset/UnsupportedCharsetException
#173 = Utf8 java/io/UnsupportedEncodingException
#174 = NameAndType #111:#115 // "<init>":(Ljava/io/OutputStream;)V
#175 = NameAndType #92:#91 // trouble:Z
#176 = NameAndType #99:#91 // closing:Z
#177 = NameAndType #90:#91 // autoFlush:Z
#178 = Utf8 java/io/OutputStreamWriter
#179 = NameAndType #97:#98 // charOut:Ljava/io/OutputStreamWriter;
#180 = Utf8 java/io/BufferedWriter
#181 = NameAndType #111:#258 // "<init>":(Ljava/io/Writer;)V
#182 = NameAndType #95:#96 // textOut:Ljava/io/BufferedWriter;
#183 = NameAndType #111:#259 // "<init>":(Ljava/io/OutputStream;Ljava/nio/charset/Charset;)V
#184 = NameAndType #111:#113 // "<init>":(ZLjava/io/OutputStream;Ljava/nio/charset/Charset;)V
#185 = NameAndType #111:#116 // "<init>":(Ljava/io/OutputStream;Z)V
#186 = Utf8 Null output stream
#187 = Utf8 java/io/OutputStream
#188 = NameAndType #111:#112 // "<init>":(ZLjava/io/OutputStream;)V
#189 = NameAndType #107:#108 // toCharset:(Ljava/lang/String;)Ljava/nio/charset/Charset;
#190 = Utf8 java/io/FileOutputStream
#191 = NameAndType #111:#114 // "<init>":(ZLjava/nio/charset/Charset;Ljava/io/OutputStream;)V
#192 = NameAndType #111:#121 // "<init>":(Ljava/io/File;)V
#193 = NameAndType #260:#261 // out:Ljava/io/OutputStream;
#194 = Utf8 java/io/IOException
#195 = Utf8 Stream closed
#196 = NameAndType #123:#124 // ensureOpen:()V
#197 = NameAndType #125:#124 // flush:()V
#198 = NameAndType #130:#124 // close:()V
#199 = Utf8 java/io/PrintStream
#200 = NameAndType #131:#132 // checkError:()Z
#201 = NameAndType #135:#136 // write:(I)V
#202 = Utf8 java/io/InterruptedIOException
#203 = Class #262 // java/lang/Thread
#204 = NameAndType #263:#264 // currentThread:()Ljava/lang/Thread;
#205 = NameAndType #265:#124 // interrupt:()V
#206 = NameAndType #135:#138 // write:([BII)V
#207 = NameAndType #135:#139 // write:([C)V
#208 = NameAndType #266:#124 // flushBuffer:()V
#209 = NameAndType #135:#118 // write:(Ljava/lang/String;)V
#210 = Class #253 // java/lang/String
#211 = NameAndType #267:#268 // indexOf:(I)I
#212 = NameAndType #140:#124 // newLine:()V
#213 = Utf8 true
#214 = Utf8 false
#215 = NameAndType #269:#270 // valueOf:(C)Ljava/lang/String;
#216 = NameAndType #269:#271 // valueOf:(I)Ljava/lang/String;
#217 = NameAndType #269:#272 // valueOf:(J)Ljava/lang/String;
#218 = NameAndType #269:#273 // valueOf:(F)Ljava/lang/String;
#219 = NameAndType #269:#274 // valueOf:(D)Ljava/lang/String;
#220 = Utf8 null
#221 = NameAndType #269:#275 // valueOf:(Ljava/lang/Object;)Ljava/lang/String;
#222 = NameAndType #141:#142 // print:(Z)V
#223 = NameAndType #141:#144 // print:(C)V
#224 = NameAndType #141:#136 // print:(I)V
#225 = NameAndType #141:#145 // print:(J)V
#226 = NameAndType #141:#146 // print:(F)V
#227 = NameAndType #141:#147 // print:(D)V
#228 = NameAndType #141:#139 // print:([C)V
#229 = NameAndType #141:#118 // print:(Ljava/lang/String;)V
#230 = NameAndType #154:#152 // format:(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream;
#231 = NameAndType #154:#153 // format:(Ljava/util/Locale;Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream;
#232 = NameAndType #93:#94 // formatter:Ljava/util/Formatter;
#233 = NameAndType #276:#277 // locale:()Ljava/util/Locale;
#234 = Class #278 // java/util/Locale
#235 = NameAndType #279:#277 // getDefault:()Ljava/util/Locale;
#236 = Utf8 java/util/Formatter
#237 = NameAndType #111:#280 // "<init>":(Ljava/lang/Appendable;)V
#238 = NameAndType #154:#281 // format:(Ljava/util/Locale;Ljava/lang/String;[Ljava/lang/Object;)Ljava/util/Formatter;
#239 = NameAndType #111:#282 // "<init>":(Ljava/lang/Appendable;Ljava/util/Locale;)V
#240 = Class #255 // java/lang/CharSequence
#241 = NameAndType #283:#284 // toString:()Ljava/lang/String;
#242 = NameAndType #285:#286 // subSequence:(II)Ljava/lang/CharSequence;
#243 = NameAndType #155:#159 // append:(C)Ljava/io/PrintStream;
#244 = NameAndType #155:#157 // append:(Ljava/lang/CharSequence;II)Ljava/io/PrintStream;
#245 = NameAndType #155:#156 // append:(Ljava/lang/CharSequence;)Ljava/io/PrintStream;
#246 = Utf8 java/io/FilterOutputStream
#247 = Utf8 java/lang/Appendable
#248 = Utf8 java/io/Closeable
#249 = Utf8 java/lang/IllegalArgumentException
#250 = Utf8 java/io/FileNotFoundException
#251 = Utf8 java/lang/Object
#252 = Utf8 java/lang/Throwable
#253 = Utf8 java/lang/String
#254 = Utf8 [C
#255 = Utf8 java/lang/CharSequence
#256 = Utf8 java/nio/charset/Charset
#257 = Utf8 forName
#258 = Utf8 (Ljava/io/Writer;)V
#259 = Utf8 (Ljava/io/OutputStream;Ljava/nio/charset/Charset;)V
#260 = Utf8 out
#261 = Utf8 Ljava/io/OutputStream;
#262 = Utf8 java/lang/Thread
#263 = Utf8 currentThread
#264 = Utf8 ()Ljava/lang/Thread;
#265 = Utf8 interrupt
#266 = Utf8 flushBuffer
#267 = Utf8 indexOf
#268 = Utf8 (I)I
#269 = Utf8 valueOf
#270 = Utf8 (C)Ljava/lang/String;
#271 = Utf8 (I)Ljava/lang/String;
#272 = Utf8 (J)Ljava/lang/String;
#273 = Utf8 (F)Ljava/lang/String;
#274 = Utf8 (D)Ljava/lang/String;
#275 = Utf8 (Ljava/lang/Object;)Ljava/lang/String;
#276 = Utf8 locale
#277 = Utf8 ()Ljava/util/Locale;
#278 = Utf8 java/util/Locale
#279 = Utf8 getDefault
#280 = Utf8 (Ljava/lang/Appendable;)V
#281 = Utf8 (Ljava/util/Locale;Ljava/lang/String;[Ljava/lang/Object;)Ljava/util/Formatter;
#282 = Utf8 (Ljava/lang/Appendable;Ljava/util/Locale;)V
#283 = Utf8 toString
#284 = Utf8 ()Ljava/lang/String;
#285 = Utf8 subSequence
#286 = Utf8 (II)Ljava/lang/CharSequence;
{
public java.io.PrintStream(java.io.OutputStream);
descriptor: (Ljava/io/OutputStream;)V
flags: ACC_PUBLIC
Code:
stack=3, locals=2, args_size=2
0: aload_0
1: aload_1
2: iconst_0
3: invokespecial #22 // Method "<init>":(Ljava/io/OutputStream;Z)V
6: return
LineNumberTable:
line 135: 0
line 136: 6
public java.io.PrintStream(java.io.OutputStream, boolean);
descriptor: (Ljava/io/OutputStream;Z)V
flags: ACC_PUBLIC
Code:
stack=4, locals=3, args_size=3
0: aload_0
1: iload_2
2: aload_1
3: ldc #23 // String Null output stream
5: invokestatic #4 // Method requireNonNull:(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;
8: checkcast #24 // class java/io/OutputStream
11: invokespecial #25 // Method "<init>":(ZLjava/io/OutputStream;)V
14: return
LineNumberTable:
line 151: 0
line 152: 14
public java.io.PrintStream(java.io.OutputStream, boolean, java.lang.String) throws java.io.UnsupportedEncodingException;
descriptor: (Ljava/io/OutputStream;ZLjava/lang/String;)V
flags: ACC_PUBLIC
Code:
stack=4, locals=4, args_size=4
0: aload_0
1: iload_2
2: aload_1
3: ldc #23 // String Null output stream
5: invokestatic #4 // Method requireNonNull:(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;
8: checkcast #24 // class java/io/OutputStream
11: aload_3
12: invokestatic #26 // Method toCharset:(Ljava/lang/String;)Ljava/nio/charset/Charset;
15: invokespecial #21 // Method "<init>":(ZLjava/io/OutputStream;Ljava/nio/charset/Charset;)V
18: return
LineNumberTable:
line 175: 0
line 176: 5
line 177: 12
line 175: 15
line 178: 18
Exceptions:
throws java.io.UnsupportedEncodingException
public java.io.PrintStream(java.lang.String) throws java.io.FileNotFoundException;
descriptor: (Ljava/lang/String;)V
flags: ACC_PUBLIC
Code:
stack=5, locals=2, args_size=2
0: aload_0
1: iconst_0
2: new #27 // class java/io/FileOutputStream
5: dup
6: aload_1
7: invokespecial #28 // Method java/io/FileOutputStream."<init>":(Ljava/lang/String;)V
10: invokespecial #25 // Method "<init>":(ZLjava/io/OutputStream;)V
13: return
LineNumberTable:
line 208: 0
line 209: 13
Exceptions:
throws java.io.FileNotFoundException
public java.io.PrintStream(java.lang.String, java.lang.String) throws java.io.FileNotFoundException, java.io.UnsupportedEncodingException;
descriptor: (Ljava/lang/String;Ljava/lang/String;)V
flags: ACC_PUBLIC
Code:
stack=6, locals=3, args_size=3
0: aload_0
1: iconst_0
2: aload_2
3: invokestatic #26 // Method toCharset:(Ljava/lang/String;)Ljava/nio/charset/Charset;
6: new #27 // class java/io/FileOutputStream
9: dup
10: aload_1
11: invokespecial #28 // Method java/io/FileOutputStream."<init>":(Ljava/lang/String;)V
14: invokespecial #29 // Method "<init>":(ZLjava/nio/charset/Charset;Ljava/io/OutputStream;)V
17: return
LineNumberTable:
line 248: 0
line 249: 17
Exceptions:
throws java.io.FileNotFoundException, java.io.UnsupportedEncodingException
public java.io.PrintStream(java.io.File) throws java.io.FileNotFoundException;
descriptor: (Ljava/io/File;)V
flags: ACC_PUBLIC
Code:
stack=5, locals=2, args_size=2
0: aload_0
1: iconst_0
2: new #27 // class java/io/FileOutputStream
5: dup
6: aload_1
7: invokespecial #30 // Method java/io/FileOutputStream."<init>":(Ljava/io/File;)V
10: invokespecial #25 // Method "<init>":(ZLjava/io/OutputStream;)V
13: return
LineNumberTable:
line 279: 0
line 280: 13
Exceptions:
throws java.io.FileNotFoundException
public java.io.PrintStream(java.io.File, java.lang.String) throws java.io.FileNotFoundException, java.io.UnsupportedEncodingException;
descriptor: (Ljava/io/File;Ljava/lang/String;)V
flags: ACC_PUBLIC
Code:
stack=6, locals=3, args_size=3
0: aload_0
1: iconst_0
2: aload_2
3: invokestatic #26 // Method toCharset:(Ljava/lang/String;)Ljava/nio/charset/Charset;
6: new #27 // class java/io/FileOutputStream
9: dup
10: aload_1
11: invokespecial #30 // Method java/io/FileOutputStream."<init>":(Ljava/io/File;)V
14: invokespecial #29 // Method "<init>":(ZLjava/nio/charset/Charset;Ljava/io/OutputStream;)V
17: return
LineNumberTable:
line 319: 0
line 320: 17
Exceptions:
throws java.io.FileNotFoundException, java.io.UnsupportedEncodingException
public void flush();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=4, args_size=1
0: aload_0
1: dup
2: astore_1
3: monitorenter
4: aload_0
5: invokespecial #35 // Method ensureOpen:()V
8: aload_0
9: getfield #31 // Field out:Ljava/io/OutputStream;
12: invokevirtual #36 // Method java/io/OutputStream.flush:()V
15: goto 24
18: astore_2
19: aload_0
20: iconst_1
21: putfield #11 // Field trouble:Z
24: aload_1
25: monitorexit
26: goto 34
29: astore_3
30: aload_1
31: monitorexit
32: aload_3
33: athrow
34: return
Exception table:
from to target type
4 15 18 Class java/io/IOException
4 26 29 any
29 32 29 any
LineNumberTable:
line 335: 0
line 337: 4
line 338: 8
line 342: 15
line 340: 18
line 341: 19
line 343: 24
line 344: 34
StackMapTable: number_of_entries = 4
frame_type = 255 /* full_frame */
offset_delta = 18
locals = [ class java/io/PrintStream, class java/lang/Object ]
stack = [ class java/io/IOException ]
frame_type = 5 /* same */
frame_type = 68 /* same_locals_1_stack_item */
stack = [ class java/lang/Throwable ]
frame_type = 250 /* chop */
offset_delta = 4
public void close();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=4, args_size=1
0: aload_0
1: dup
2: astore_1
3: monitorenter
4: aload_0
5: getfield #12 // Field closing:Z
8: ifne 54
11: aload_0
12: iconst_1
13: putfield #12 // Field closing:Z
16: aload_0
17: getfield #19 // Field textOut:Ljava/io/BufferedWriter;
20: invokevirtual #37 // Method java/io/BufferedWriter.close:()V
23: aload_0
24: getfield #31 // Field out:Ljava/io/OutputStream;
27: invokevirtual #38 // Method java/io/OutputStream.close:()V
30: goto 39
33: astore_2
34: aload_0
35: iconst_1
36: putfield #11 // Field trouble:Z
39: aload_0
40: aconst_null
41: putfield #19 // Field textOut:Ljava/io/BufferedWriter;
44: aload_0
45: aconst_null
46: putfield #16 // Field charOut:Ljava/io/OutputStreamWriter;
49: aload_0
50: aconst_null
51: putfield #31 // Field out:Ljava/io/OutputStream;
54: aload_1
55: monitorexit
56: goto 64
59: astore_3
60: aload_1
61: monitorexit
62: aload_3
63: athrow
64: return
Exception table:
from to target type
16 30 33 Class java/io/IOException
4 56 59 any
59 62 59 any
LineNumberTable:
line 355: 0
line 356: 4
line 357: 11
line 359: 16
line 360: 23
line 364: 30
line 362: 33
line 363: 34
line 365: 39
line 366: 44
line 367: 49
line 369: 54
line 370: 64
StackMapTable: number_of_entries = 5
frame_type = 255 /* full_frame */
offset_delta = 33
locals = [ class java/io/PrintStream, class java/lang/Object ]
stack = [ class java/io/IOException ]
frame_type = 5 /* same */
frame_type = 14 /* same */
frame_type = 68 /* same_locals_1_stack_item */
stack = [ class java/lang/Throwable ]
frame_type = 250 /* chop */
offset_delta = 4
public boolean checkError();
descriptor: ()Z
flags: ACC_PUBLIC
Code:
stack=1, locals=2, args_size=1
0: aload_0
1: getfield #31 // Field out:Ljava/io/OutputStream;
4: ifnull 11
7: aload_0
8: invokevirtual #39 // Method flush:()V
11: aload_0
12: getfield #31 // Field out:Ljava/io/OutputStream;
15: instanceof #40 // class java/io/PrintStream
18: ifeq 34
21: aload_0
22: getfield #31 // Field out:Ljava/io/OutputStream;
25: checkcast #40 // class java/io/PrintStream
28: astore_1
29: aload_1
30: invokevirtual #41 // Method checkError:()Z
33: ireturn
34: aload_0
35: getfield #11 // Field trouble:Z
38: ireturn
LineNumberTable:
line 391: 0
line 392: 7
line 393: 11
line 394: 21
line 395: 29
line 397: 34
StackMapTable: number_of_entries = 2
frame_type = 11 /* same */
frame_type = 22 /* same */
protected void setError();
descriptor: ()V
flags: ACC_PROTECTED
Code:
stack=2, locals=1, args_size=1
0: aload_0
1: iconst_1
2: putfield #11 // Field trouble:Z
5: return
LineNumberTable:
line 410: 0
line 411: 5
protected void clearError();
descriptor: ()V
flags: ACC_PROTECTED
Code:
stack=2, locals=1, args_size=1
0: aload_0
1: iconst_0
2: putfield #11 // Field trouble:Z
5: return
LineNumberTable:
line 423: 0
line 424: 5
public void write(int);
descriptor: (I)V
flags: ACC_PUBLIC
Code:
stack=2, locals=4, args_size=2
0: aload_0
1: dup
2: astore_2
3: monitorenter
4: aload_0
5: invokespecial #35 // Method ensureOpen:()V
8: aload_0
9: getfield #31 // Field out:Ljava/io/OutputStream;
12: iload_1
13: invokevirtual #42 // Method java/io/OutputStream.write:(I)V
16: iload_1
17: bipush 10
19: if_icmpne 36
22: aload_0
23: getfield #13 // Field autoFlush:Z
26: ifeq 36
29: aload_0
30: getfield #31 // Field out:Ljava/io/OutputStream;
33: invokevirtual #36 // Method java/io/OutputStream.flush:()V
36: aload_2
37: monitorexit
38: goto 46
41: astore_3
42: aload_2
43: monitorexit
44: aload_3
45: athrow
46: goto 65
49: astore_2
50: invokestatic #44 // Method java/lang/Thread.currentThread:()Ljava/lang/Thread;
53: invokevirtual #45 // Method java/lang/Thread.interrupt:()V
56: goto 65
59: astore_2
60: aload_0
61: iconst_1
62: putfield #11 // Field trouble:Z
65: return
Exception table:
from to target type
4 38 41 any
41 44 41 any
0 46 49 Class java/io/InterruptedIOException
0 46 59 Class java/io/IOException
LineNumberTable:
line 447: 0
line 448: 4
line 449: 8
line 450: 16
line 451: 29
line 452: 36
line 459: 46
line 454: 49
line 455: 50
line 459: 56
line 457: 59
line 458: 60
line 460: 65
StackMapTable: number_of_entries = 6
frame_type = 252 /* append */
offset_delta = 36
locals = [ class java/lang/Object ]
frame_type = 68 /* same_locals_1_stack_item */
stack = [ class java/lang/Throwable ]
frame_type = 250 /* chop */
offset_delta = 4
frame_type = 66 /* same_locals_1_stack_item */
stack = [ class java/io/InterruptedIOException ]
frame_type = 73 /* same_locals_1_stack_item */
stack = [ class java/io/IOException ]
frame_type = 5 /* same */
public void write(byte[], int, int);
descriptor: ([BII)V
flags: ACC_PUBLIC
Code:
stack=4, locals=6, args_size=4
0: aload_0
1: dup
2: astore 4
4: monitorenter
5: aload_0
6: invokespecial #35 // Method ensureOpen:()V
9: aload_0
10: getfield #31 // Field out:Ljava/io/OutputStream;
13: aload_1
14: iload_2
15: iload_3
16: invokevirtual #46 // Method java/io/OutputStream.write:([BII)V
19: aload_0
20: getfield #13 // Field autoFlush:Z
23: ifeq 33
26: aload_0
27: getfield #31 // Field out:Ljava/io/OutputStream;
30: invokevirtual #36 // Method java/io/OutputStream.flush:()V
33: aload 4
35: monitorexit
36: goto 47
39: astore 5
41: aload 4
43: monitorexit
44: aload 5
46: athrow
47: goto 68
50: astore 4
52: invokestatic #44 // Method java/lang/Thread.currentThread:()Ljava/lang/Thread;
55: invokevirtual #45 // Method java/lang/Thread.interrupt:()V
58: goto 68
61: astore 4
63: aload_0
64: iconst_1
65: putfield #11 // Field trouble:Z
68: return
Exception table:
from to target type
5 36 39 any
39 44 39 any
0 47 50 Class java/io/InterruptedIOException
0 47 61 Class java/io/IOException
LineNumberTable:
line 478: 0
line 479: 5
line 480: 9
line 481: 19
line 482: 26
line 483: 33
line 490: 47
line 485: 50
line 486: 52
line 490: 58
line 488: 61
line 489: 63
line 491: 68
StackMapTable: number_of_entries = 6
frame_type = 252 /* append */
offset_delta = 33
locals = [ class java/lang/Object ]
frame_type = 69 /* same_locals_1_stack_item */
stack = [ class java/lang/Throwable ]
frame_type = 250 /* chop */
offset_delta = 7
frame_type = 66 /* same_locals_1_stack_item */
stack = [ class java/io/InterruptedIOException ]
frame_type = 74 /* same_locals_1_stack_item */
stack = [ class java/io/IOException ]
frame_type = 6 /* same */
public void print(boolean);
descriptor: (Z)V
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: iload_1
2: ifeq 10
5: ldc #53 // String true
7: goto 12
10: ldc #54 // String false
12: invokespecial #55 // Method write:(Ljava/lang/String;)V
15: return
LineNumberTable:
line 571: 0
line 572: 15
StackMapTable: number_of_entries = 2
frame_type = 74 /* same_locals_1_stack_item */
stack = [ class java/io/PrintStream ]
frame_type = 255 /* full_frame */
offset_delta = 1
locals = [ class java/io/PrintStream, int ]
stack = [ class java/io/PrintStream, class java/lang/String ]
public void print(char);
descriptor: (C)V
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: iload_1
2: invokestatic #56 // Method java/lang/String.valueOf:(C)Ljava/lang/String;
5: invokespecial #55 // Method write:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 583: 0
line 584: 8
public void print(int);
descriptor: (I)V
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: iload_1
2: invokestatic #57 // Method java/lang/String.valueOf:(I)Ljava/lang/String;
5: invokespecial #55 // Method write:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 597: 0
line 598: 8
public void print(long);
descriptor: (J)V
flags: ACC_PUBLIC
Code:
stack=3, locals=3, args_size=2
0: aload_0
1: lload_1
2: invokestatic #58 // Method java/lang/String.valueOf:(J)Ljava/lang/String;
5: invokespecial #55 // Method write:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 611: 0
line 612: 8
public void print(float);
descriptor: (F)V
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: fload_1
2: invokestatic #59 // Method java/lang/String.valueOf:(F)Ljava/lang/String;
5: invokespecial #55 // Method write:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 625: 0
line 626: 8
public void print(double);
descriptor: (D)V
flags: ACC_PUBLIC
Code:
stack=3, locals=3, args_size=2
0: aload_0
1: dload_1
2: invokestatic #60 // Method java/lang/String.valueOf:(D)Ljava/lang/String;
5: invokespecial #55 // Method write:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 639: 0
line 640: 8
public void print(char[]);
descriptor: ([C)V
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: aload_1
2: invokespecial #61 // Method write:([C)V
5: return
LineNumberTable:
line 653: 0
line 654: 5
public void print(java.lang.String);
descriptor: (Ljava/lang/String;)V
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: aload_1
1: ifnonnull 7
4: ldc #62 // String null
6: astore_1
7: aload_0
8: aload_1
9: invokespecial #55 // Method write:(Ljava/lang/String;)V
12: return
LineNumberTable:
line 666: 0
line 667: 4
line 669: 7
line 670: 12
StackMapTable: number_of_entries = 1
frame_type = 7 /* same */
public void print(java.lang.Object);
descriptor: (Ljava/lang/Object;)V
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: aload_1
2: invokestatic #63 // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
5: invokespecial #55 // Method write:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 683: 0
line 684: 8
public void println();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #64 // Method newLine:()V
4: return
LineNumberTable:
line 696: 0
line 697: 4
public void println(boolean);
descriptor: (Z)V
flags: ACC_PUBLIC
Code:
stack=2, locals=4, args_size=2
0: aload_0
1: dup
2: astore_2
3: monitorenter
4: aload_0
5: iload_1
6: invokevirtual #65 // Method print:(Z)V
9: aload_0
10: invokespecial #64 // Method newLine:()V
13: aload_2
14: monitorexit
15: goto 23
18: astore_3
19: aload_2
20: monitorexit
21: aload_3
22: athrow
23: return
Exception table:
from to target type
4 15 18 any
18 21 18 any
LineNumberTable:
line 707: 0
line 708: 4
line 709: 9
line 710: 13
line 711: 23
StackMapTable: number_of_entries = 2
frame_type = 255 /* full_frame */
offset_delta = 18
locals = [ class java/io/PrintStream, int, class java/lang/Object ]
stack = [ class java/lang/Throwable ]
frame_type = 250 /* chop */
offset_delta = 4
public void println(char);
descriptor: (C)V
flags: ACC_PUBLIC
Code:
stack=2, locals=4, args_size=2
0: aload_0
1: dup
2: astore_2
3: monitorenter
4: aload_0
5: iload_1
6: invokevirtual #66 // Method print:(C)V
9: aload_0
10: invokespecial #64 // Method newLine:()V
13: aload_2
14: monitorexit
15: goto 23
18: astore_3
19: aload_2
20: monitorexit
21: aload_3
22: athrow
23: return
Exception table:
from to target type
4 15 18 any
18 21 18 any
LineNumberTable:
line 721: 0
line 722: 4
line 723: 9
line 724: 13
line 725: 23
StackMapTable: number_of_entries = 2
frame_type = 255 /* full_frame */
offset_delta = 18
locals = [ class java/io/PrintStream, int, class java/lang/Object ]
stack = [ class java/lang/Throwable ]
frame_type = 250 /* chop */
offset_delta = 4
public void println(int);
descriptor: (I)V
flags: ACC_PUBLIC
Code:
stack=2, locals=4, args_size=2
0: aload_0
1: dup
2: astore_2
3: monitorenter
4: aload_0
5: iload_1
6: invokevirtual #67 // Method print:(I)V
9: aload_0
10: invokespecial #64 // Method newLine:()V
13: aload_2
14: monitorexit
15: goto 23
18: astore_3
19: aload_2
20: monitorexit
21: aload_3
22: athrow
23: return
Exception table:
from to target type
4 15 18 any
18 21 18 any
LineNumberTable:
line 735: 0
line 736: 4
line 737: 9
line 738: 13
line 739: 23
StackMapTable: number_of_entries = 2
frame_type = 255 /* full_frame */
offset_delta = 18
locals = [ class java/io/PrintStream, int, class java/lang/Object ]
stack = [ class java/lang/Throwable ]
frame_type = 250 /* chop */
offset_delta = 4
public void println(long);
descriptor: (J)V
flags: ACC_PUBLIC
Code:
stack=3, locals=5, args_size=2
0: aload_0
1: dup
2: astore_3
3: monitorenter
4: aload_0
5: lload_1
6: invokevirtual #68 // Method print:(J)V
9: aload_0
10: invokespecial #64 // Method newLine:()V
13: aload_3
14: monitorexit
15: goto 25
18: astore 4
20: aload_3
21: monitorexit
22: aload 4
24: athrow
25: return
Exception table:
from to target type
4 15 18 any
18 22 18 any
LineNumberTable:
line 749: 0
line 750: 4
line 751: 9
line 752: 13
line 753: 25
StackMapTable: number_of_entries = 2
frame_type = 255 /* full_frame */
offset_delta = 18
locals = [ class java/io/PrintStream, long, class java/lang/Object ]
stack = [ class java/lang/Throwable ]
frame_type = 250 /* chop */
offset_delta = 6
public void println(float);
descriptor: (F)V
flags: ACC_PUBLIC
Code:
stack=2, locals=4, args_size=2
0: aload_0
1: dup
2: astore_2
3: monitorenter
4: aload_0
5: fload_1
6: invokevirtual #69 // Method print:(F)V
9: aload_0
10: invokespecial #64 // Method newLine:()V
13: aload_2
14: monitorexit
15: goto 23
18: astore_3
19: aload_2
20: monitorexit
21: aload_3
22: athrow
23: return
Exception table:
from to target type
4 15 18 any
18 21 18 any
LineNumberTable:
line 763: 0
line 764: 4
line 765: 9
line 766: 13
line 767: 23
StackMapTable: number_of_entries = 2
frame_type = 255 /* full_frame */
offset_delta = 18
locals = [ class java/io/PrintStream, float, class java/lang/Object ]
stack = [ class java/lang/Throwable ]
frame_type = 250 /* chop */
offset_delta = 4
public void println(double);
descriptor: (D)V
flags: ACC_PUBLIC
Code:
stack=3, locals=5, args_size=2
0: aload_0
1: dup
2: astore_3
3: monitorenter
4: aload_0
5: dload_1
6: invokevirtual #70 // Method print:(D)V
9: aload_0
10: invokespecial #64 // Method newLine:()V
13: aload_3
14: monitorexit
15: goto 25
18: astore 4
20: aload_3
21: monitorexit
22: aload 4
24: athrow
25: return
Exception table:
from to target type
4 15 18 any
18 22 18 any
LineNumberTable:
line 777: 0
line 778: 4
line 779: 9
line 780: 13
line 781: 25
StackMapTable: number_of_entries = 2
frame_type = 255 /* full_frame */
offset_delta = 18
locals = [ class java/io/PrintStream, double, class java/lang/Object ]
stack = [ class java/lang/Throwable ]
frame_type = 250 /* chop */
offset_delta = 6
public void println(char[]);
descriptor: ([C)V
flags: ACC_PUBLIC
Code:
stack=2, locals=4, args_size=2
0: aload_0
1: dup
2: astore_2
3: monitorenter
4: aload_0
5: aload_1
6: invokevirtual #71 // Method print:([C)V
9: aload_0
10: invokespecial #64 // Method newLine:()V
13: aload_2
14: monitorexit
15: goto 23
18: astore_3
19: aload_2
20: monitorexit
21: aload_3
22: athrow
23: return
Exception table:
from to target type
4 15 18 any
18 21 18 any
LineNumberTable:
line 791: 0
line 792: 4
line 793: 9
line 794: 13
line 795: 23
StackMapTable: number_of_entries = 2
frame_type = 255 /* full_frame */
offset_delta = 18
locals = [ class java/io/PrintStream, class "[C", class java/lang/Object ]
stack = [ class java/lang/Throwable ]
frame_type = 250 /* chop */
offset_delta = 4
public void println(java.lang.String);
descriptor: (Ljava/lang/String;)V
flags: ACC_PUBLIC
Code:
stack=2, locals=4, args_size=2
0: aload_0
1: dup
2: astore_2
3: monitorenter
4: aload_0
5: aload_1
6: invokevirtual #72 // Method print:(Ljava/lang/String;)V
9: aload_0
10: invokespecial #64 // Method newLine:()V
13: aload_2
14: monitorexit
15: goto 23
18: astore_3
19: aload_2
20: monitorexit
21: aload_3
22: athrow
23: return
Exception table:
from to target type
4 15 18 any
18 21 18 any
LineNumberTable:
line 805: 0
line 806: 4
line 807: 9
line 808: 13
line 809: 23
StackMapTable: number_of_entries = 2
frame_type = 255 /* full_frame */
offset_delta = 18
locals = [ class java/io/PrintStream, class java/lang/String, class java/lang/Object ]
stack = [ class java/lang/Throwable ]
frame_type = 250 /* chop */
offset_delta = 4
public void println(java.lang.Object);
descriptor: (Ljava/lang/Object;)V
flags: ACC_PUBLIC
Code:
stack=2, locals=5, args_size=2
0: aload_1
1: invokestatic #63 // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
4: astore_2
5: aload_0
6: dup
7: astore_3
8: monitorenter
9: aload_0
10: aload_2
11: invokevirtual #72 // Method print:(Ljava/lang/String;)V
14: aload_0
15: invokespecial #64 // Method newLine:()V
18: aload_3
19: monitorexit
20: goto 30
23: astore 4
25: aload_3
26: monitorexit
27: aload 4
29: athrow
30: return
Exception table:
from to target type
9 20 23 any
23 27 23 any
LineNumberTable:
line 821: 0
line 822: 5
line 823: 9
line 824: 14
line 825: 18
line 826: 30
StackMapTable: number_of_entries = 2
frame_type = 255 /* full_frame */
offset_delta = 23
locals = [ class java/io/PrintStream, class java/lang/Object, class java/lang/String, class java/lang/Object ]
stack = [ class java/lang/Throwable ]
frame_type = 250 /* chop */
offset_delta = 6
public java.io.PrintStream printf(java.lang.String, java.lang.Object...);
descriptor: (Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream;
flags: ACC_PUBLIC, ACC_VARARGS
Code:
stack=3, locals=3, args_size=3
0: aload_0
1: aload_1
2: aload_2
3: invokevirtual #73 // Method format:(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream;
6: areturn
LineNumberTable:
line 871: 0
public java.io.PrintStream printf(java.util.Locale, java.lang.String, java.lang.Object...);
descriptor: (Ljava/util/Locale;Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream;
flags: ACC_PUBLIC, ACC_VARARGS
Code:
stack=4, locals=4, args_size=4
0: aload_0
1: aload_1
2: aload_2
3: aload_3
4: invokevirtual #74 // Method format:(Ljava/util/Locale;Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream;
7: areturn
LineNumberTable:
line 921: 0
public java.io.PrintStream format(java.lang.String, java.lang.Object...);
descriptor: (Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream;
flags: ACC_PUBLIC, ACC_VARARGS
Code:
stack=4, locals=5, args_size=3
0: aload_0
1: dup
2: astore_3
3: monitorenter
4: aload_0
5: invokespecial #35 // Method ensureOpen:()V
8: aload_0
9: getfield #75 // Field formatter:Ljava/util/Formatter;
12: ifnull 28
15: aload_0
16: getfield #75 // Field formatter:Ljava/util/Formatter;
19: invokevirtual #76 // Method java/util/Formatter.locale:()Ljava/util/Locale;
22: invokestatic #77 // Method java/util/Locale.getDefault:()Ljava/util/Locale;
25: if_acmpeq 40
28: aload_0
29: new #78 // class java/util/Formatter
32: dup
33: aload_0
34: invokespecial #79 // Method java/util/Formatter."<init>":(Ljava/lang/Appendable;)V
37: putfield #75 // Field formatter:Ljava/util/Formatter;
40: aload_0
41: getfield #75 // Field formatter:Ljava/util/Formatter;
44: invokestatic #77 // Method java/util/Locale.getDefault:()Ljava/util/Locale;
47: aload_1
48: aload_2
49: invokevirtual #80 // Method java/util/Formatter.format:(Ljava/util/Locale;Ljava/lang/String;[Ljava/lang/Object;)Ljava/util/Formatter;
52: pop
53: aload_3
54: monitorexit
55: goto 65
58: astore 4
60: aload_3
61: monitorexit
62: aload 4
64: athrow
65: goto 84
68: astore_3
69: invokestatic #44 // Method java/lang/Thread.currentThread:()Ljava/lang/Thread;
72: invokevirtual #45 // Method java/lang/Thread.interrupt:()V
75: goto 84
78: astore_3
79: aload_0
80: iconst_1
81: putfield #11 // Field trouble:Z
84: aload_0
85: areturn
Exception table:
from to target type
4 55 58 any
58 62 58 any
0 65 68 Class java/io/InterruptedIOException
0 65 78 Class java/io/IOException
LineNumberTable:
line 965: 0
line 966: 4
line 967: 8
line 968: 19
line 969: 28
line 970: 40
line 971: 53
line 976: 65
line 972: 68
line 973: 69
line 976: 75
line 974: 78
line 975: 79
line 977: 84
StackMapTable: number_of_entries = 7
frame_type = 252 /* append */
offset_delta = 28
locals = [ class java/lang/Object ]
frame_type = 11 /* same */
frame_type = 81 /* same_locals_1_stack_item */
stack = [ class java/lang/Throwable ]
frame_type = 250 /* chop */
offset_delta = 6
frame_type = 66 /* same_locals_1_stack_item */
stack = [ class java/io/InterruptedIOException ]
frame_type = 73 /* same_locals_1_stack_item */
stack = [ class java/io/IOException ]
frame_type = 5 /* same */
public java.io.PrintStream format(java.util.Locale, java.lang.String, java.lang.Object...);
descriptor: (Ljava/util/Locale;Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream;
flags: ACC_PUBLIC, ACC_VARARGS
Code:
stack=5, locals=6, args_size=4
0: aload_0
1: dup
2: astore 4
4: monitorenter
5: aload_0
6: invokespecial #35 // Method ensureOpen:()V
9: aload_0
10: getfield #75 // Field formatter:Ljava/util/Formatter;
13: ifnull 27
16: aload_0
17: getfield #75 // Field formatter:Ljava/util/Formatter;
20: invokevirtual #76 // Method java/util/Formatter.locale:()Ljava/util/Locale;
23: aload_1
24: if_acmpeq 40
27: aload_0
28: new #78 // class java/util/Formatter
31: dup
32: aload_0
33: aload_1
34: invokespecial #81 // Method java/util/Formatter."<init>":(Ljava/lang/Appendable;Ljava/util/Locale;)V
37: putfield #75 // Field formatter:Ljava/util/Formatter;
40: aload_0
41: getfield #75 // Field formatter:Ljava/util/Formatter;
44: aload_1
45: aload_2
46: aload_3
47: invokevirtual #80 // Method java/util/Formatter.format:(Ljava/util/Locale;Ljava/lang/String;[Ljava/lang/Object;)Ljava/util/Formatter;
50: pop
51: aload 4
53: monitorexit
54: goto 65
57: astore 5
59: aload 4
61: monitorexit
62: aload 5
64: athrow
65: goto 86
68: astore 4
70: invokestatic #44 // Method java/lang/Thread.currentThread:()Ljava/lang/Thread;
73: invokevirtual #45 // Method java/lang/Thread.interrupt:()V
76: goto 86
79: astore 4
81: aload_0
82: iconst_1
83: putfield #11 // Field trouble:Z
86: aload_0
87: areturn
Exception table:
from to target type
5 54 57 any
57 62 57 any
0 65 68 Class java/io/InterruptedIOException
0 65 79 Class java/io/IOException
LineNumberTable:
line 1022: 0
line 1023: 5
line 1024: 9
line 1025: 20
line 1026: 27
line 1027: 40
line 1028: 51
line 1033: 65
line 1029: 68
line 1030: 70
line 1033: 76
line 1031: 79
line 1032: 81
line 1034: 86
StackMapTable: number_of_entries = 7
frame_type = 252 /* append */
offset_delta = 27
locals = [ class java/lang/Object ]
frame_type = 12 /* same */
frame_type = 80 /* same_locals_1_stack_item */
stack = [ class java/lang/Throwable ]
frame_type = 250 /* chop */
offset_delta = 7
frame_type = 66 /* same_locals_1_stack_item */
stack = [ class java/io/InterruptedIOException ]
frame_type = 74 /* same_locals_1_stack_item */
stack = [ class java/io/IOException ]
frame_type = 6 /* same */
public java.io.PrintStream append(java.lang.CharSequence);
descriptor: (Ljava/lang/CharSequence;)Ljava/io/PrintStream;
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: aload_1
1: ifnonnull 13
4: aload_0
5: ldc #62 // String null
7: invokevirtual #72 // Method print:(Ljava/lang/String;)V
10: goto 23
13: aload_0
14: aload_1
15: invokeinterface #82, 1 // InterfaceMethod java/lang/CharSequence.toString:()Ljava/lang/String;
20: invokevirtual #72 // Method print:(Ljava/lang/String;)V
23: aload_0
24: areturn
LineNumberTable:
line 1062: 0
line 1063: 4
line 1065: 13
line 1066: 23
StackMapTable: number_of_entries = 2
frame_type = 13 /* same */
frame_type = 9 /* same */
public java.io.PrintStream append(java.lang.CharSequence, int, int);
descriptor: (Ljava/lang/CharSequence;II)Ljava/io/PrintStream;
flags: ACC_PUBLIC
Code:
stack=4, locals=5, args_size=4
0: aload_1
1: ifnonnull 9
4: ldc #62 // String null
6: goto 10
9: aload_1
10: astore 4
12: aload_0
13: aload 4
15: iload_2
16: iload_3
17: invokeinterface #83, 3 // InterfaceMethod java/lang/CharSequence.subSequence:(II)Ljava/lang/CharSequence;
22: invokeinterface #82, 1 // InterfaceMethod java/lang/CharSequence.toString:()Ljava/lang/String;
27: invokespecial #55 // Method write:(Ljava/lang/String;)V
30: aload_0
31: areturn
LineNumberTable:
line 1103: 0
line 1104: 12
line 1105: 30
StackMapTable: number_of_entries = 2
frame_type = 9 /* same */
frame_type = 64 /* same_locals_1_stack_item */
stack = [ class java/lang/CharSequence ]
public java.io.PrintStream append(char);
descriptor: (C)Ljava/io/PrintStream;
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: iload_1
2: invokevirtual #66 // Method print:(C)V
5: aload_0
6: areturn
LineNumberTable:
line 1125: 0
line 1126: 5
public java.lang.Appendable append(char) throws java.io.IOException;
descriptor: (C)Ljava/lang/Appendable;
flags: ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: iload_1
2: invokevirtual #84 // Method append:(C)Ljava/io/PrintStream;
5: areturn
LineNumberTable:
line 57: 0
Exceptions:
throws java.io.IOException
public java.lang.Appendable append(java.lang.CharSequence, int, int) throws java.io.IOException;
descriptor: (Ljava/lang/CharSequence;II)Ljava/lang/Appendable;
flags: ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
Code:
stack=4, locals=4, args_size=4
0: aload_0
1: aload_1
2: iload_2
3: iload_3
4: invokevirtual #85 // Method append:(Ljava/lang/CharSequence;II)Ljava/io/PrintStream;
7: areturn
LineNumberTable:
line 57: 0
Exceptions:
throws java.io.IOException
public java.lang.Appendable append(java.lang.CharSequence) throws java.io.IOException;
descriptor: (Ljava/lang/CharSequence;)Ljava/lang/Appendable;
flags: ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: aload_1
2: invokevirtual #86 // Method append:(Ljava/lang/CharSequence;)Ljava/io/PrintStream;
5: areturn
LineNumberTable:
line 57: 0
Exceptions:
throws java.io.IOException
}
SourceFile: "PrintStream.java"
rchaser53noMacBook-Pro:rj rchaser53$
javapでjava/io/PrintStreamのクラスファイルの実装を表示
回避策
ビルトインのクラスについて
-
今回はビルトインのクラスに関してはRustで代用
- 同様のオペランド スタックの挙動をさせることで対応
- 実行時に予め読み込ませる形を取った
- オペランド スタックはJVMが計算や引数、戻り値に使用するスタック
2. ブラウザ上でWasmとして実行
-
wasm-bindgenを利用してWasmを生成
ドキュメントもそれなりに充実している - RustとJS間の値の受け渡しをある程度やってくれる
RustとJS間の値の受け渡しをある程度やってくれる
2. ブラウザ上でWasmとして実行
// RustでJavaScriptの関数のネイティブの関数を呼び出したい
#[wasm_bindgen]
extern "C" {
pub fn alert(s: &str);
}
// RustでJavaScriptの関数の自作の関数を呼び出したい
/* Rust側 */
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen(module = "/web/map.js")]
extern "C" {
pub fn get_file_content_from_js(key: &str) -> Vec<u8>;
}
/* JavaScript側 */
fn get_file_content_from_js(key) {
// 実際にはclassの情報を持ったobjectがあり、引数のkeyで値を取得する
const testData = new Uint8Array([
202, 254, 186, 190 // CA, FE, BA, BE ... Javaのclass fileの最初のやつ。magic
]);
return testData;
}
現状はまだまだ制限もある
2. ブラウザ上でWasmとして実行
// referencesは返せない
/* error: cannot return references in #[wasm_bindgen] imports yet */
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen(module = "/web/map.js")]
extern "C" {
pub fn get_file_content_from_js(key: &str) -> &[u8];
}
// lifetimeや型パラメータは使えない
/* error: can't #[wasm_bindgen] functions with lifetime or type parameters */
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen(module = "/web/map.js")]
extern "C" {
pub fn get_file_content_from_js<'a>'(key: &'a str) -> Vec<u8>;
}
-
FizzBuzz
実際に動かしてみる
-
多次元配列とインスタンスの生成
実際に動かしてみる
今回割と上手くいったこと
-
言語を開発する度に毎度デバッグに苦しめられている
-
以下の2点を導入したら、デバッグ効率が改善された
-
javapライクの機能の生成
-
状態を1命令ごとに出力し続ける機能の作成
-
- 次回以降の自作言語関連の開発に活かそうと思う
今回割と上手くいったこと
javapライクの機能の生成
-
JVMの処理としてバイナリから情報を抽出する必要がある
- 今回は1クラスファイル、1structという形で抽出した
- そもそも間違った形式で抽出していては話にならない
- javapと似たフォーマットでDebug情報を出力する
- スタート地点でこけていないか確認できるようにした
今回割と上手くいったこと
状態を1命令ごとに出力し続ける機能の作成
-
どこかの命令で状態の変更を失敗するのが大体の原因
- 状態遷移を明示すれば失敗した箇所を見つけやすいのでは
-
ビルトインクラスの実装
-
非同期処理の実装
-
バイナリのvalidationの実装
-
継承、インターフェイスの実装
今回できなかったこと、やらなかったこと
-
楽しい
-
仕様書からでも以外と書ける
-
実装量が暴力的に多い。1人では無理では?
-
VMだけでは思ったより何もできない
-
デバッグしやすさは重要
まとめや感想
参考資料
ご静聴ありがとうございました
Rust製JVMを作成した話
By rchaser53
Rust製JVMを作成した話
ついでにWasmでブラウザで動かす
- 14,748