rhino(javascript)generated bytecode for method exceeds 64K

众所周知,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对象了,如果可以被编译,那么就执行字节码,如果编译失败,就解释执行,虽然影响性能,但在没有更好的解决方案的时候,也不影响程序的功能。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值