sealing violation

一般以下两种情况会触发sealing安全异常
1)当被密封(seal)的package已经被加载,此时再试图去加载其他jar中的同名package,就会触发sealing violation异常
2)当没有被密封的package已经被加载,此时再去加载其他jar中同名且被密封的package,也会触发sealing violation异常


假设某次发布的jar(v1.jar)中包含NumerUtils和StringUtils这俩工具类
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)
*/

你可能感兴趣的:(java,sealing)