Pack200 /网络传输格式规格说明SourceDebugExtension属性

如果你尝试用pack200打包spring-context 5.0.1.RELEASE JAR,打包者会抱怨说它不知道在Kotlin类中编译的类中使用的类属性SourceDebugExtension


JSR-045将此属性定义为

 The SourceDebugExtension attribute is an optional attribute in the attributes table of the ClassFile structure. There can be no more than one SourceDebugExtension attribute in the attributes table of a given ClassFile structure. The SourceDebugExtension attribute has the following format: SourceDebugExtension_attribute { u2 attribute_name_index; u4 attribute_length; u1 debug_extension[attribute_length]; } The items of the SourceDebugExtension_attribute structure are as follows: attribute_name_index The value of the attribute_name_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Utf8_info structure representing the string "SourceDebugExtension". attribute_length The value of the attribute_length item indicates the length of the attribute, excluding the initial six bytes. The value of the attribute_length item is thus the number of bytes in the debug_extension[] item. debug_extension[] The debug_extension array holds a string, which must be in UTF-8 format. There is no terminating zero byte. The string in the debug_extension item will be interpreted as extended debugging information. The content of this string has no semantic effect on the Java Virtual Machine. 

网络传输格式规范定义了如何定义这些属性的格式,以便pack200可以处理它们。


Pack200允许跳过具有这些属性的文件,或者根据网络传输格式规范抛出这些属性或定义它们的格式。 Unfortunatley我没有得到正确的解析正确的属性的格式说明符。 需要由格式说明符匹配的实际数据的一个示例Hexdump – 这是debug_extension[]的值是

 00000b90: 53 4d 41 50 0a 42 65 61 6e 44 ; SMAP.BeanD 00000ba0: 65 66 69 6e 69 74 69 6f 6e 44 73 6c 2e 6b 74 0a ;efinitionDsl.kt. 00000bb0: 4b 6f 74 6c 69 6e 0a 2a 53 20 4b 6f 74 6c 69 6e ;Kotlin.*S Kotlin 00000bc0: 0a 2a 46 0a 2b 20 31 20 42 65 61 6e 44 65 66 69 ;.*F.+ 1 BeanDefi 00000bd0: 6e 69 74 69 6f 6e 44 73 6c 2e 6b 74 0a 6f 72 67 ;nitionDsl.kt.org 00000be0: 2f 73 70 72 69 6e 67 66 72 61 6d 65 77 6f 72 6b ;/springframework 00000bf0: 2f 63 6f 6e 74 65 78 74 2f 73 75 70 70 6f 72 74 ;/context/support 00000c00: 2f 42 65 61 6e 44 65 66 69 6e 69 74 69 6f 6e 44 ;/BeanDefinitionD 00000c10: 73 6c 24 62 65 61 6e 24 31 24 63 75 73 74 6f 6d ;sl$bean$1$custom 00000c20: 69 7a 65 72 24 31 0a 2a 4c 0a 31 23 31 2c 32 37 ;izer$1.*L.1#1,27 00000c30: 33 3a 31 0a 2a 45 0a ;3:1.*E. 

不幸的是,我还没有找到正确的格式。 我希望这里已经有人或者找到正确的格式有更多的运气。

最后我自己找到了一个工作解决方案

格式有点棘手,因为SourceDebugExtension属性被定义为一个直接的UTF-8字符串,没有任何像\0这样的终止字符,而在格式化字符串中,你不能像“取所有剩余字节”或“直到结束字节数组到达“。

但是在阅读了格式化字符串的可能性和SourceDebugExtension属性的内容格式之后,我想出了一种在大多数情况下SourceDebugExtension正常工作的格式。

SourceDebugExtension属性携带已解析的SMAP。 在这种情况下解决这个问题非常重要,因为在一个未解决的SMAP中,可能会嵌入SMAP,这些SMAP已经包含了一个结束部分,这会使其更加复杂,但并非不可能。 在已解析的SMAP中,您始终有<line terminator>*E<line terminator> ,其中<line terminator>可能是通常的嫌疑犯\r\n\r\n并且此序列不可能出现在SMAP如果解决了。

现在我们可以使用带有递归自调用的union布局元素来构建以下格式的字符串,在大多数情况下,它们将正确匹配SMAP。 这个格式字符串唯一假设的是,如果在*E之前找到行终止符\r\n ,那么在它之后也是可以的,如果之前只有\r\n被找到,则\r\n是预计之后。 哪一个不重要,只是不是\r\n 。 如果发生这种情况,包装会失败,抱怨一个字节没有处理。 但是如果我们要检查两个字符,而且只剩下一个字符,我们就会得到一个ArrayIndexOutOfBoundsException ,我认为这是不太可能的情况,不同的行结束符是混合的。

所以在这里我目前的做法:

 [TB(10)[TB(42)[TB(69)[TB(13,10)[]()[(0)]]()[(0)]]()[(0)]](13)[TB(10)[TB(42)[TB(69)[TB(13)[TB(10)[]()[(0)]]()[(0)]]()[(0)]]()[(0)]](42)[TB(69)[TB(13,10)[]()[(0)]]()[(0)]]()[(0)]]()[(0)]] 

为了更好的理解这里的格式和一些空格和语义内容。 像这样,它不能直接使用。 它必须通过com.sun.java.util.jar.pack.Attribute#normalizeLayoutString传递,这是一个包 – 私有类中的public static方法,因此经常无法访问。 如果你使用反射或Groovy来为你做,或者将方法体复制到你自己的方法中,你当然可以在你的代码中使用这个版本。

 [ # covered likely cases: # \\n*E\\n # \\r\\n*E\\r\\n # \\r*E\\r # # covered unlikely cases: # \\n*E\\r # \\r*E\\n # # uncovered unlikely cases: # \\n*E\\r\\n # \\r*E\\r\\n # \\r\\n*E\\r # \\r\\n*E\\n TB (\\\n) [ # covered cases: # \\n*E\\r # \\n*E\\n TB (\\*) [ TB (\\E) [ TB (\\\r, \\\n) [] () [(0)] ] () [(0)] ] () [(0)] ] (\\\r) [ # covered cases: # \\r\\n*E\\r\\n # \\r*E\\r # \\r*E\\n TB (\\\n) [ # covered cases: # \\r\\n*E\\r\\n TB (\\*) [ TB (\\E) [ TB (\\\r) [ TB (\\\n) [] () [(0)] ] () [(0)] ] () [(0)] ] () [(0)] ] (\\*) [ # covered cases: # \\r*E\\r # \\r*E\\n TB (\\E) [ TB (\\\r, \\\n) [] () [(0)] ] () [(0)] ] () [(0)] ] () [(0)] ]