rhino(javascript)generated bytecode for method exceeds 64K


周知のように、jdk 1.6にはダイナミックスクリプトのサポートが追加されており、javaでjsスクリプトを実行することができ、jdk 1.4,1.5でこの機能を使用する場合は、http://www.mozilla.org/rhino/で提供されているjarを使用することができ、jdk 1.6はこのオープンソースプロジェクトをjdk(jsr_223)に統合することができる.
 
ブラウザでは、jsは解釈実行であり、javaではjavascriptスクリプトにwindow、documentなどのオブジェクトはもちろんありませんが、javascriptの強さには影響しません.解釈実行もできますし、コンパイル実行もできます.効率が大幅に向上します.コンパイルとは、javascriptスクリプトをjavaメソッドのバイトコードにコンパイルすることです.
 
タイトルのエラーEncountered code generation error while compiling script:generated bytecode for method exceeds 64 K Rhinoを使用してjsスクリプトをコンパイルするときに発生します.Rhinoの実装を確認します.org.mozilla.classfile.classFileWriterのpublic voidstopMethod(short maxLocals)メソッドには、次のコードがあります.
 
if (attrLength > 65536) {
	// See http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html,
	// section 4.10, "The amount of code per non-native, non-abstract 
	// method is limited to 65536 bytes...
	throw new ClassFileFormatException(
		"generated bytecode for method exceeds 64K limit.");
}
 
 
すなわち、Methodのbytecodeの長さが65536バイト(64 K)を超えると、このようなエラーが報告される.
 
1999年にMaximum method size is too small (64Kb)という理由で公式にバグとして提出された人もいますが、これまでは少なくとも1.5では変更されておらず、1.6でも変更されていないようです
 
このコードの注釈部分では、jvm spec第2版の4.10章が方法の長さに規定されているということを見ることができます.私はここで以下を抜粋します.
 
4.10 Limitations of the Java Virtual MachineThe following limitations of the Java virtual machine are implicit in the class file format:
 
The per-class or per-interface constant pool is limited to 65535 entries by the 16-bit constant_pool_count field of the ClassFile structure (§4.1) . This acts as an internal limit on the total complexity of a single class or interface.
 
The amount of code per non-native, non-abstract method is limited to 65536 bytes by the sizes of the indices in the exception_table of the Code attribute ( §4.7.3) , in the LineNumberTable attribute (§4.7.8) , and in the LocalVariableTable attribute (§4.7.9) .
 
The greatest number of local variables in the local variables array of a frame created upon invocation of a method is limited to 65535 by the size of the max_locals item of the Code attribute (§4.7.3) giving the code of the method. Note that values of type long and double are each considered to reserve two local variables and contribute two units toward the max_locals value, so use of local variables of those types further reduces this limit.
 
The number of fields that may be declared by a class or interface is limited to 65535 by the size of the fields_count item of the ClassFile structure (§4.1) . Note that the value of the fields_count item of the ClassFile structure does not include fields that are inherited from superclasses or superinterfaces.
 
The number of methods that may be declared by a class or interface is limited to 65535 by the size of the methods_count item of the ClassFile structure (§4.1) . Note that the value of the methods_count item of the ClassFile structure does not include methods that are inherited from superclasses or superinterfaces.
 
The number of direct superinterfaces of a class or interface is limited to 65535 by the size of the interfaces_count item of the ClassFile structure (§4.1) .
 
The size of an operand stack in a frame (§3.6) is limited to 65535 values by the max_stack field of the Code_attribute structure (§4.7.3) . Note that values of type long and double are each considered to contribute two units toward the max_stack value, so use of values of these types on the operand stack further reduces this limit.
 
The number of local variables in a frame (§3.6) is limited to 65535 by the max_locals field of the Code_attribute structure (§4.7.3) and the 16-bit local variable indexing of the Java virtual machine instruction set.
 
The number of dimensions in an array is limited to 255 by the size of thedimensionsopcode of themultianewarrayinstruction and by the constraints imposed on themultianewarray,anewarray, andnewarrayinstructions by §4.8.2 .
 
The number of method parameters is limited to 255 by the definition of a method descriptor (§4.3.3) , where the limit includes one unit for this in the case of instance or interface method invocations. Note that a method descriptor is defined in terms of a notion of method parameter length in which a parameter of type long or double contributes two units to the length, so parameters of these types further reduce the limit.
 
The length of field and method names, field and method descriptors, and other constant string values is limited to 65535 characters by the 16-bit unsigned length item of the CONSTANT_Utf8_info structure (§4.4.7) . Note that the limit is on the number of bytes in the encoding and not on the number of encoded characters. UTF-8 encodes some characters using two or three bytes. Thus, strings incorporating multibyte characters are further constrained. 
 
 
シャドウ部分の内容ですが、コンパイルできない場合はどうすればいいのでしょうか.実行を説明できるのは明らかですが、もちろん方法体を小さく分けることもできますが、方法が自動的に生成される場合があります.私たちもこのような内容を変更したくない場合があります.Rhinoでコンパイル実行方法をどのように説明しますか.一部のコードは以下の通りです.
 
 
String scriptContent = ".........";//   js  ,                 
org.mozilla.javascript.Context  context = org.mozilla.javascript.Context.enter();
org.mozilla.javascript.Script  script = null;
try {
        script = context.compileString(scriptContent , null, 1, null);
} catch (Throwable t) {
        context.setOptimizationLevel(-1);
        script = context.compileString(scriptContent , null, 1, null);
}
 
 
//ここでは上記のscriptオブジェクトを実行できます.コンパイル可能であればバイトコードを実行し、コンパイルに失敗すれば実行を解釈します.パフォーマンスに影響しますが、より良い解決策がない場合は、プログラムの機能にも影響しません.