一般以下两种情况会触发sealing安全异常
1)当被密封(seal)的package已经被加载,此时再试图去加载其他jar中的同名package,就会触发sealing violation异常
2)当没有被密封的package已经被加载,此时再去加载其他jar中同名且被密封的package,也会触发sealing violation异常
假设某次发布的jar(v1.jar)中包含NumerUtils和StringUtils这俩工具类
class="java" name="code">package com.seal.util;
import java.text.DecimalFormat;
public class NumberUtils {
public static String format(double d) {
return new DecimalFormat("#,##0.00").format(d);
}
}
package com.seal.util;
public class StringUtils {
public static String format(String str) {
return "Format:" + str;
}
}
/**
javac -d v1 NumberUtils.java StringUtils.java
编译源文件至v1目录,多个源文件用空格分隔
jar -cvfm v1.jar mf.mf -C v1 .
将v1目录下的所有子目录和文件都压缩成jar文件,
jar文件的MANIFEST.MF采用自己定义的mf.mf
mf.mf内容如下:
Manifest-Version: 1.0
Created-By: 1.6.0_33 (Sun Microsystems Inc.)
Name: com/seal/util/
Sealed: true
*/
一段时间后,需要对该v1.jar进行升级,加入一个新的工具类DateUtils.java
同样的,采用上面的步骤进行编译、打包得到v2.jar
package com.seal.util;
import java.util.Date;
import java.text.SimpleDateFormat;
public class DateUtils {
public static String format(Date date) {
return new SimpleDateFormat("yyyy-MM-dd").format(date);
}
}
import com.seal.util.NumberUtils;
import com.seal.util.StringUtils;
import com.seal.util.DateUtils;
public class MainTest {
public static void main(String[] args) {
System.out.println(NumberUtils.format(1.2));
System.out.println(StringUtils.format("str"));
System.out.println(DateUtils.format(new java.util.Date()));
}
}
/**
javac -cp v1.jar;v2.jar MainTest.java
编译MainTest源文件
java -cp .;v1.jar;v2.jar MainTest
运行MainTest 此时classpath同时包含v1.jar跟v2.jar
因为jvm加载package的顺序是根据jar在classpath出现的先后顺便来进行的,所以此时先从v1.jar加载了seal的com.seal.util,但是DateUtils需要从v2.jar获得,所以就会触发sealing violation安全异常
Exception in thread "main" java.lang.SecurityException: sealing violation: packa
ge com.seal.util is sealed
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$000(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at MainTest.main(MainTest.java:10)
相反的,如果一开始加载的v1的package不是seal的,要从v2加载seal的同名package就会触发另一个sealing violation安全异常
Exception in thread "main" java.lang.SecurityException: sealing violation: can't
seal package com.seal.util: already loaded
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$000(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at MainTest.main(MainTest.java:10)
*/