一文读懂jar包的小秘密( 二 )


一般来说,目录结构是这样的:META-INF/versions/N
其中N表示的是JDK的主要发行版本,比如9,10,11等 。
类加载器会先去META-INF/versions/N目录中加载所需要的class,然后会去其他的低版本的META-INF/versions/N目录中加载所需要的class,最后才会在META-INF/的根目录加载其他的class文件 。
MANIFEST.MF详解MANIFEST.MF中存放的是key:value格式的配置信息,这些配置信息又可以分成两部分,第一部分是main-section信息,第二部分是individual-section 。
我们举个简单的例子:
Manifest-Version: 1.0Created-By: 1.8 (Oracle Inc.)Sealed: trueName: foo/bar/Sealed: false其中
Manifest-Version: 1.0Created-By: 1.8 (Oracle Inc.)Sealed: true就是main-section信息,我们用一张图来看一下main-section的信息有哪些:

一文读懂jar包的小秘密

文章插图
 
在main-section信息下发可以接一个Name: Value,表示开启独立的针对于具体entry的属性(Per-Entry Attributes)配置:
【一文读懂jar包的小秘密】Name: foo/bar/Sealed: false比如上面的属性是专门针对于包foo/bar/的,并且设置其Sealed属性为false 。
Per-Entry Attributes除了 package versioning 和 sealing信息外,还可以定义Content-Type,Java-Bean,x-Digest-y和Magic属性 。
JAR包签名JAR包可以通过使用jarsigner来对其进行签名 。和签名相关的文件是:
  • META-INF/MANIFEST.MF
  • META-INF/*.SF
  • META-INF/*.DSA
  • META-INF/*.RSA
  • META-INF/SIG-*
签名过后的jar跟原来的jar其实并没有什么不同,只不过在META-INF/文件夹中多出了两个文件,一个是签名文件,一个是签名block文件 。
签名文件签名文件是以.SF结尾的,这个文件和MANIFEST.MF很类似,可以指定Signature-Version和Created-By 。
除此之外,还可以指定和安全相关的属性:
  • x-Digest-Manifest-Main-Attributes: 其中x是java.security.MessageDigest中指定的算法,表示的主要属性的摘要 。
  • x-Digest-Manifest: 表示的是整个manifest的摘要 。
这两个属性主要用来做验证签名用的 。
举个例子:
如果我们的manifest是下面这样的:
Manifest-Version: 1.0Created-By: 1.8.0 (Oracle Inc.)Name: common/class1.classSHA-256-Digest: (base64 representation of SHA-256 digest)Name: common/class2.classSHA1-Digest: (base64 representation of SHA1 digest)SHA-256-Digest: (base64 representation of SHA-256 digest)那么相应的签名文件应该是这样的:
Signature-Version: 1.0SHA-256-Digest-Manifest: (base64 representation of SHA-256 digest)SHA-256-Digest-Manifest-Main-Attributes: (base64 representation of SHA-256 digest)Name: common/class1.classSHA-256-Digest: (base64 representation of SHA-256 digest)Name: common/class2.classSHA-256-Digest: (base64 representation of SHA-256 digest)签名文件的摘要如果再对.SF文件进行摘要,那么就会得到签名文件的摘要文件:
  • .RSA (PKCS7 signature, SHA-256 + RSA)
  • .DSA (PKCS7 signature, DSA)
Sealed上面我们讲到了一个Sealed属性:
Name: javax/servlet/internal/Sealed: true这个属性的意思是,javax/servlet/internal/包中的所有类必须从这个jar包中加载 。
这个属性主要是从jar包的安全性来考虑的 。


推荐阅读