Pack200 /网络传输格式SourceDebugExtension属性的规范格式规范

时间:2017-10-27 10:13:46

标签: java format pack

如果你试图用pack200打包spring-context 5.0.1.RELEASE JAR,那么打包器会抱怨它不知道在那里编译的几个类中使用的类属性SourceDebugExtension Kotlin课程。

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.

Network Transfer Format Spec定义了如何定义这些属性的格式,以便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.

不幸的是我还没能找到正确的格式。我希望有人在这里做过这件事或者找到合适的格式会更幸运。

1 个答案:

答案 0 :(得分:0)

最后,我自己找到了一个有效的解决方案。

格式有点棘手,因为SourceDebugExtension属性被定义为直接的UTF-8字符串,没有任何终止字符,如\0,在格式字符串中你不能定义类似&#34的字符串;取所有剩余字节"或"直到到达字节数组的末尾"。

但是在阅读了格式字符串的可能性以及SourceDebugExtension属性的内容格式之后,我提出了一种在大多数情况下应该有用的格式。

SourceDebugExtension属性带有已解析的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)]
]