JRuby/初期化を読む
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
#contents
*はじめに [#w03e10ac]
今回はJRubyを読みます。JRubyではRubyスクリプトをJavaVMの...
なお、対象としたバージョンは1.7.3です。
*org.jruby.Main [#g2e3da49]
まずはmainメソッドが定義されているクラスを探します。org.j...
+Mainインスタンスの生成
++RubyInstanceConfigインスタンスの生成
+runメソッドの実行
++引数の解析(RubyInstanceConfigインスタンスに委譲)
++Rubyインスタンスの生成、以後の処理はRubyインスタンスに...
という処理が行われています。
*org.jruby.RubyInstanceConfig [#h6c98e2f]
RubyInstanceConfigは各種の情報を格納するクラスです。RubyI...
-VMに関するもの
--互換バージョン
--実行方法(コンパイルするのかインタープリトするのか)など
-スクリプトに関するもの
--スクリプトの入力元(ファイルかコマンドライン引数か)
--スクリプトへの引数など
*org.jruby.Ruby [#t7673c00]
**initメソッド [#n0b56d6c]
Rubyインスタンスが生成される際、initメソッドが呼ばれます...
***initRootメソッド [#q2f361a7]
initRootメソッドではまずRubyソース愛読者にはおなじみのObj...
その後、Kernelモジュール、top self、Nilクラス、Falseクラ...
***bootstrapメソッド [#n794c041]
bootstrapメソッドはinitCoreメソッドとinitExceptionsメソッ...
***initBuiltinsメソッド [#nd5fb465]
initBuiltinsメソッドではビルトインライブラリの登録が行わ...
#code(Java){{
addLazyBuiltin("java.rb", "java", "org.jruby.javasupport....
}}
見た感じ、java.rbをrequireするとorg.jruby.javasupport.Jav...
***initRubyKernelメソッド [#qeaecb1e]
initRubyKernelメソッドではKernelモジュールにメソッドを定...
*メソッドの定義 [#d190eb95]
ところでKernelモジュールを構築しているRubyKernel.createKe...
#code(Java){{
public static RubyModule createKernelModule(Ruby runtime) {
RubyModule module = runtime.defineModule("Kernel");
runtime.setKernel(module);
module.defineAnnotatedMethods(RubyKernel.class);
module.setFlag(RubyObject.USER7_F, false); //Kernel i...
runtime.setPrivateMethodMissing(new MethodMissingMeth...
@Override
public IRubyObject methodMissing(ThreadContext co...
return RubyKernel.methodMissing(context, self...
}
});
(中略)
recacheBuiltinMethods(runtime);
return module;
}
}}
それっぽいのはdefineAnnotateMethodsメソッドを呼んでいると...
#code(Java){{
@JRubyMethod(name = "p", rest = true, module = true, visi...
public static IRubyObject p(ThreadContext context, IRubyO...
(省略)
}
}}
のように書いてあるのでどうやらアノテーションでRubyのメソ...
というわけで、
org.jruby.RubyModule.defineAnnotateMethods
→ org.jruby.RubyModule.defineAnnotatedMethodsIndividually
→ org.jruby.anno.TypePopulator.DefaultTypePopulator.popu...
とコードを追っていくと、
#code(Java){{
public void populate(RubyModule clsmod, Class clazz) {
// fallback on non-pregenerated logic
MethodFactory methodFactory = MethodFactory.createFac...
Ruby runtime = clsmod.getRuntime();
RubyModule.MethodClumper clumper = new RubyModule.Met...
clumper.clump(clazz);
for (Map.Entry<String, List<JavaMethodDescriptor>> en...
for (JavaMethodDescriptor desc : entry.getValue()...
JRubyMethod anno = desc.anno;
// check for frame field reads or writes
if (anno.frame() || (anno.reads() != null && ...
// add all names for this annotation
ASTInspector.addFrameAwareMethods(anno.na...
// TODO: separate scope-aware and frame-a...
ASTInspector.addScopeAwareMethods(anno.na...
}
}
}
for (Map.Entry<String, List<JavaMethodDescriptor>> en...
clsmod.defineAnnotatedMethod(entry.getKey(), entr...
for (JavaMethodDescriptor desc : entry.getValue()...
if (!desc.anno.omit()) runtime.addBoundMethod...
}
}
for (Map.Entry<String, List<JavaMethodDescriptor>> en...
clsmod.defineAnnotatedMethod(entry.getKey(), entr...
for (JavaMethodDescriptor desc : entry.getValue()...
if (!desc.anno.omit()) runtime.addBoundMethod...
}
}
for (Map.Entry<String, List<JavaMethodDescriptor>> en...
clsmod.defineAnnotatedMethod(entry.getKey(), entr...
for (JavaMethodDescriptor desc : entry.getValue()...
if (!desc.anno.omit()) runtime.addBoundMethod...
}
}
for (Map.Entry<String, List<JavaMethodDescriptor>> en...
clsmod.defineAnnotatedMethod(entry.getKey(), entr...
for (JavaMethodDescriptor desc : entry.getValue()...
if (!desc.anno.omit()) runtime.addBoundMethod...
}
}
(1.9と2.0用メソッドについて同様)
}
}}
とアノテーション情報を収集してメソッドを定義している様子...
RubyModule.defineAnnotatedMethodメソッドに進みます。
#code(Java){{
public boolean defineAnnotatedMethod(String name, List<Ja...
JavaMethodDescriptor desc = methods.get(0);
if (methods.size() == 1) {
return defineAnnotatedMethod(desc, methodFactory);
} else {
DynamicMethod dynamicMethod = methodFactory.getAn...
define(this, desc, dynamicMethod);
return true;
}
}
}}
メソッド数が1つか複数かで処理が分かれています。メソッド数...
#code(Java){{
public class RubyArray extends RubyObject implements List...
...
@JRubyMethod(name = {"[]", "slice"}, compat = RUBY1_9)
public IRubyObject aref19(IRubyObject arg0) {
return arg0 instanceof RubyFixnum ? entry(((RubyF...
}
private IRubyObject arefCommon(IRubyObject arg0) {
if (arg0 instanceof RubyRange) {
long[] beglen = ((RubyRange) arg0).begLen(rea...
return beglen == null ? getRuntime().getNil()...
}
return entry(RubyNumeric.num2long(arg0));
}
@JRubyMethod(name = {"[]", "slice"}, compat = RUBY1_9)
public IRubyObject aref19(IRubyObject arg0, IRubyObje...
return arefCommon(arg0, arg1);
}
private IRubyObject arefCommon(IRubyObject arg0, IRub...
long beg = RubyNumeric.num2long(arg0);
if (beg < 0) beg += realLength;
return subseq(beg, RubyNumeric.num2long(arg1));
}
...
}
}}
みたいな場合です。上の[]はself[nth]とself[range]、下の[]...
MethodFactoryは抽象クラスでその実体はデフォルトではInvoca...
#code(Java){{
public DynamicMethod getAnnotatedMethod(RubyModule implem...
JavaMethodDescriptor desc1 = descs.get(0);
String javaMethodName = desc1.name;
try {
Class c = getAnnotatedMethodClass(descs);
DescriptorInfo info = new DescriptorInfo(descs);
JavaMethod ic = (JavaMethod)c.getConstructor(new ...
TypePopulator.populateMethod(
ic,
Arity.optional().getValue(),
javaMethodName,
desc1.isStatic,
CallConfiguration.getCallConfig(info.isFr...
desc1.anno.notImplemented(),
desc1.getDeclaringClass(),
desc1.name,
desc1.getReturnClass(),
desc1.getParameterClasses());
return ic;
} catch(Exception e) {
e.printStackTrace();
throw implementationClass.getRuntime().newLoadErr...
}
}
}}
getAnnotatedMethodClassメソッドに進むと非常に面白いことが...
ところでメソッド数が1つの場合でも複数の場合でも結局同じよ...
*おわりに [#od3dda8f]
今回はJRubyのうち、初期化の部分を読みました。その結果、以...
-Rubyメソッド実装はアノテーションで定義
-引数の数が異なる場合、メソッド実装をオーバーロードするこ...
-アノテーションで定義されたメソッド実装の呼び出しはクラス...
実はまだメソッド実装がオーバーロードされている場合にどう...
というわけで次はスクリプト解析→実行の部分に進みます。
終了行:
#contents
*はじめに [#w03e10ac]
今回はJRubyを読みます。JRubyではRubyスクリプトをJavaVMの...
なお、対象としたバージョンは1.7.3です。
*org.jruby.Main [#g2e3da49]
まずはmainメソッドが定義されているクラスを探します。org.j...
+Mainインスタンスの生成
++RubyInstanceConfigインスタンスの生成
+runメソッドの実行
++引数の解析(RubyInstanceConfigインスタンスに委譲)
++Rubyインスタンスの生成、以後の処理はRubyインスタンスに...
という処理が行われています。
*org.jruby.RubyInstanceConfig [#h6c98e2f]
RubyInstanceConfigは各種の情報を格納するクラスです。RubyI...
-VMに関するもの
--互換バージョン
--実行方法(コンパイルするのかインタープリトするのか)など
-スクリプトに関するもの
--スクリプトの入力元(ファイルかコマンドライン引数か)
--スクリプトへの引数など
*org.jruby.Ruby [#t7673c00]
**initメソッド [#n0b56d6c]
Rubyインスタンスが生成される際、initメソッドが呼ばれます...
***initRootメソッド [#q2f361a7]
initRootメソッドではまずRubyソース愛読者にはおなじみのObj...
その後、Kernelモジュール、top self、Nilクラス、Falseクラ...
***bootstrapメソッド [#n794c041]
bootstrapメソッドはinitCoreメソッドとinitExceptionsメソッ...
***initBuiltinsメソッド [#nd5fb465]
initBuiltinsメソッドではビルトインライブラリの登録が行わ...
#code(Java){{
addLazyBuiltin("java.rb", "java", "org.jruby.javasupport....
}}
見た感じ、java.rbをrequireするとorg.jruby.javasupport.Jav...
***initRubyKernelメソッド [#qeaecb1e]
initRubyKernelメソッドではKernelモジュールにメソッドを定...
*メソッドの定義 [#d190eb95]
ところでKernelモジュールを構築しているRubyKernel.createKe...
#code(Java){{
public static RubyModule createKernelModule(Ruby runtime) {
RubyModule module = runtime.defineModule("Kernel");
runtime.setKernel(module);
module.defineAnnotatedMethods(RubyKernel.class);
module.setFlag(RubyObject.USER7_F, false); //Kernel i...
runtime.setPrivateMethodMissing(new MethodMissingMeth...
@Override
public IRubyObject methodMissing(ThreadContext co...
return RubyKernel.methodMissing(context, self...
}
});
(中略)
recacheBuiltinMethods(runtime);
return module;
}
}}
それっぽいのはdefineAnnotateMethodsメソッドを呼んでいると...
#code(Java){{
@JRubyMethod(name = "p", rest = true, module = true, visi...
public static IRubyObject p(ThreadContext context, IRubyO...
(省略)
}
}}
のように書いてあるのでどうやらアノテーションでRubyのメソ...
というわけで、
org.jruby.RubyModule.defineAnnotateMethods
→ org.jruby.RubyModule.defineAnnotatedMethodsIndividually
→ org.jruby.anno.TypePopulator.DefaultTypePopulator.popu...
とコードを追っていくと、
#code(Java){{
public void populate(RubyModule clsmod, Class clazz) {
// fallback on non-pregenerated logic
MethodFactory methodFactory = MethodFactory.createFac...
Ruby runtime = clsmod.getRuntime();
RubyModule.MethodClumper clumper = new RubyModule.Met...
clumper.clump(clazz);
for (Map.Entry<String, List<JavaMethodDescriptor>> en...
for (JavaMethodDescriptor desc : entry.getValue()...
JRubyMethod anno = desc.anno;
// check for frame field reads or writes
if (anno.frame() || (anno.reads() != null && ...
// add all names for this annotation
ASTInspector.addFrameAwareMethods(anno.na...
// TODO: separate scope-aware and frame-a...
ASTInspector.addScopeAwareMethods(anno.na...
}
}
}
for (Map.Entry<String, List<JavaMethodDescriptor>> en...
clsmod.defineAnnotatedMethod(entry.getKey(), entr...
for (JavaMethodDescriptor desc : entry.getValue()...
if (!desc.anno.omit()) runtime.addBoundMethod...
}
}
for (Map.Entry<String, List<JavaMethodDescriptor>> en...
clsmod.defineAnnotatedMethod(entry.getKey(), entr...
for (JavaMethodDescriptor desc : entry.getValue()...
if (!desc.anno.omit()) runtime.addBoundMethod...
}
}
for (Map.Entry<String, List<JavaMethodDescriptor>> en...
clsmod.defineAnnotatedMethod(entry.getKey(), entr...
for (JavaMethodDescriptor desc : entry.getValue()...
if (!desc.anno.omit()) runtime.addBoundMethod...
}
}
for (Map.Entry<String, List<JavaMethodDescriptor>> en...
clsmod.defineAnnotatedMethod(entry.getKey(), entr...
for (JavaMethodDescriptor desc : entry.getValue()...
if (!desc.anno.omit()) runtime.addBoundMethod...
}
}
(1.9と2.0用メソッドについて同様)
}
}}
とアノテーション情報を収集してメソッドを定義している様子...
RubyModule.defineAnnotatedMethodメソッドに進みます。
#code(Java){{
public boolean defineAnnotatedMethod(String name, List<Ja...
JavaMethodDescriptor desc = methods.get(0);
if (methods.size() == 1) {
return defineAnnotatedMethod(desc, methodFactory);
} else {
DynamicMethod dynamicMethod = methodFactory.getAn...
define(this, desc, dynamicMethod);
return true;
}
}
}}
メソッド数が1つか複数かで処理が分かれています。メソッド数...
#code(Java){{
public class RubyArray extends RubyObject implements List...
...
@JRubyMethod(name = {"[]", "slice"}, compat = RUBY1_9)
public IRubyObject aref19(IRubyObject arg0) {
return arg0 instanceof RubyFixnum ? entry(((RubyF...
}
private IRubyObject arefCommon(IRubyObject arg0) {
if (arg0 instanceof RubyRange) {
long[] beglen = ((RubyRange) arg0).begLen(rea...
return beglen == null ? getRuntime().getNil()...
}
return entry(RubyNumeric.num2long(arg0));
}
@JRubyMethod(name = {"[]", "slice"}, compat = RUBY1_9)
public IRubyObject aref19(IRubyObject arg0, IRubyObje...
return arefCommon(arg0, arg1);
}
private IRubyObject arefCommon(IRubyObject arg0, IRub...
long beg = RubyNumeric.num2long(arg0);
if (beg < 0) beg += realLength;
return subseq(beg, RubyNumeric.num2long(arg1));
}
...
}
}}
みたいな場合です。上の[]はself[nth]とself[range]、下の[]...
MethodFactoryは抽象クラスでその実体はデフォルトではInvoca...
#code(Java){{
public DynamicMethod getAnnotatedMethod(RubyModule implem...
JavaMethodDescriptor desc1 = descs.get(0);
String javaMethodName = desc1.name;
try {
Class c = getAnnotatedMethodClass(descs);
DescriptorInfo info = new DescriptorInfo(descs);
JavaMethod ic = (JavaMethod)c.getConstructor(new ...
TypePopulator.populateMethod(
ic,
Arity.optional().getValue(),
javaMethodName,
desc1.isStatic,
CallConfiguration.getCallConfig(info.isFr...
desc1.anno.notImplemented(),
desc1.getDeclaringClass(),
desc1.name,
desc1.getReturnClass(),
desc1.getParameterClasses());
return ic;
} catch(Exception e) {
e.printStackTrace();
throw implementationClass.getRuntime().newLoadErr...
}
}
}}
getAnnotatedMethodClassメソッドに進むと非常に面白いことが...
ところでメソッド数が1つの場合でも複数の場合でも結局同じよ...
*おわりに [#od3dda8f]
今回はJRubyのうち、初期化の部分を読みました。その結果、以...
-Rubyメソッド実装はアノテーションで定義
-引数の数が異なる場合、メソッド実装をオーバーロードするこ...
-アノテーションで定義されたメソッド実装の呼び出しはクラス...
実はまだメソッド実装がオーバーロードされている場合にどう...
というわけで次はスクリプト解析→実行の部分に進みます。
ページ名: