论坛首页 Java企业应用论坛

rhino(javascript)generated bytecode for method exceeds 64K

浏览 3033 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2010-12-28   最后修改:2011-04-18

众所周知,jdk1.6中添加了对动态脚本的支持,可以在java中执行js脚本,如果要在jdk1.4,1.5下使用这个功能,可以使用http://www.mozilla.org/rhino/上提供的jar,jdk1.6将这个开源项目集成进了jdk(jsr_223)。

 

在浏览器中,js是解释执行的,在java中,javascript脚本自然没有了window,document等对象,但这不影响javascript的强大,可以解释执行,也可以编译执行,大大提高了效率,所谓编译,也就是把javascript脚本编译成java方法的字节码。

 

标题中的错误Encountered code generation error while compiling script: generated bytecode for method exceeds 64K 是在使用Rhino编译js脚本的时候发生的,查看Rhino的实现,在org.mozilla.classfile.ClassFileWriterpublic 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字节(64K)的时候,就会报这样的错误。

 

有人在1999年已经以Maximum method size is too small (64Kb)为由作为bug提交给了官方,但至今,至少在1.5中都没有改变,1.6中似乎也没有改变

 

在这一段代码的注释部分,我们可以看到,说jvm spec第二版中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对象了,如果可以被编译,那么就执行字节码,如果编译失败,就解释执行,虽然影响性能,但在没有更好的解决方案的时候,也不影响程序的功能。

 

   发表时间:2010-12-28  
呃嗯,真够杯具的。在JSR 202相应的大小规定仍然如此,方法最多不能超过64K字节。
引用
The value of the code_length item must be less than 65536.
0 请登录后投票
   发表时间:2011-03-28  
想请问一个问题,关于第一段中“把javascript脚本编译成java方法的字节码。”这句话,JavaScript编译成的字节码和java的是一样的吗?如果不一样的话,有什么区别。望不吝赐教。谢谢
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics