gpt4 book ai didi

java - 密封 .jar 时会密封哪些特定包?

转载 作者:搜寻专家 更新时间:2023-10-31 20:09:08 27 4
gpt4 key购买 nike

当封装一个.jar 文件(整个.jar,而不是特定的包)时,实际上封装了哪些包?它只是包含.class 文件的包,还是还包含父包和子包?

举个例子,假设我有一个包含单个 .class 文件 com.company.city.london.class 的 .jar,它只是 com.company.city 密封的包裹?

JVM 是否允许我在 .jar 之外创建和实例化 com.company.city.building.house.class 类?

JVM 是否允许我在 .jar 之外创建和实例化 com.company.world.class 类?

最佳答案

OK,写完测试应用,我就有答案了。在阅读文档后,它们并不完全符合我的预期。

我将以下两个类打包到一个已密封的 .jar 中:

测试类.java:

package com.company.testjar;

public class TestClass {
}

测试类2.java:

package com.company.testjar2;

public class TestClass2 {
}

.jar list 如下所示:

Manifest-Version: 1.0
Ant-Version: Apache Ant 1.9.3
Created-By: 1.8.0_40-b26 (Oracle Corporation)
Implementation-Vendor: Company
Implementation-Title: Test Jar
Implementation-Version: 6.4.0.0
Sealed: true

根据文档,密封整个 .jar 会密封 .jar 中的所有包。但是,我发现这种说法是模棱两可的。

然后我编写了一些 JUnit 测试用例,看看我可以定义哪些其他类而不会导致密封的 .jar 出现问题。

对于我的单元测试,我还添加了以下三个测试类。请注意,这些未在 .jar 中定义,但使用相同的包结构 - 这对测试很重要。

假的.java:

package com.company.testjar;

public class Bogus {
}

SubBogus.java

package com.company.testjar.subpackage;

public class SubBogus {
}

ParentBogus.java:

package com.company;

public class ParentBogus {
}

JUnit 测试:

package com.company.test;

import static org.junit.Assert.*;

import org.junit.Test;

import com.company.ParentBogus;
import com.company.testjar.Bogus;
import com.company.testjar.TestClass;
import com.company.testjar.subpackage.SubBogus;
import com.company.testjar2.TestClass2;

/**
* A set of tests for testing the effects of .jar sealing.
*
* These tests rely on a built .jar named TestJar.jar which is built from the command line.
*
* Only one of these tests can be run at a time because one a package has been loaded, it cannot
* be unloaded again. Because of this, each test must be run separately.
*/
public class TestPackages {

@Test
public void SealedFail1() {
// Instantiate instance of TestClass from sealed .jar.
TestClass t = new TestClass();

// Following should blow up because package com.company.testjar has already
// been loaded by instantiating TestClass above.
try {
new Bogus();

// Should not get here. Throw if we do.
assertFalse(true);
} catch (SecurityException ex) {
// Expected.
}
}

@Test
public void SealedFail2() {
Bogus b = new Bogus();

// Following should blow up because package com.company.testjar has already
// been loaded by instantiating Bogus above.
try {
new TestClass();

// Should not get here. Throw if we do.
assertFalse(true);
} catch (SecurityException ex) {
// Expected.
}
}

/**
* Test to see if instantiating object from package in a sealed .jar will effectively
* load and seal all packages in that .jar.
*/
@Test
public void SealedFail3() {
// Instantiate object from com.company.testjar2 package. This package will now be
// loaded and sealed.
TestClass2 t2 = new TestClass2();

// Instantiate object from com.company.testjar package NOT from sealed .jar.
// This should work because this package has not been sealed yet!
Bogus b = new Bogus();

// This should now throw because the com.company.testjar package has already
// been loaded by instantiating Bogus above, and the TestClass is from that
// same package from the sealed .jar.
try {
new TestClass();

// Should not get here. Throw if we do.
assertFalse(true);
} catch (SecurityException ex) {
// Expected.
}
}

/**
* Test to see if instantiating an object from a sealed .jar prevents us from then
* instantiating an instance of an object from a sub-package NOT defined in the
* same .jar.
*/
@Test
public void SubPackage() {
// Instantiate instance of TestClass from sealed .jar. Loads and seals the
// com.company.testjar package.
TestClass t = new TestClass();

// Now attempt to instantiate an instance of an object from a sub-package of
// com.company.testjar which is not defined in the same .jar.
new SubBogus();
}

/**
* Test to see if instantiating an object from a sealed .jar prevents us from then
* instantiating an instance of an object from a parent package NOT defined in the
* same .jar.
*/
@Test
public void ParentPackage() {
// Instantiate instance of TestClass from sealed .jar. Loads and seals the
// com.company.testjar package.
TestClass t = new TestClass();

// Now attempt to instantiate an instance of an object from the parent-package of
// com.company.testjar which is not defined in the same .jar.
new ParentBogus();
}
}

单独的测试应该独立运行,因为一旦加载了一个包,我就不会再次卸载它并且会影响测试的结果。如果一次运行所有测试,将会出现失败,因为包由第一个测试加载并保持加载状态。

当单独运行时,所有测试都通过了。

从这些测试中,我们可以确定以下内容:

  1. 密封整个 .jar 并不会密封空的父包。因此以下空包未密封:“com”和“com.company”。只有包含类的包是密封的。请参阅测试 ParentPackage()。
  2. 如果您通过从 .jar 实例化一个类来从 .jar 加载一个包,然后尝试从 .jar 外部的同一个包加载一个类,这将失败。请参阅测试 SealedFail1()。
  3. 如果您通过实例化一个与 .jar 中的 .class 共享相同包名的类从 .jar 外部加载包,则尝试从同一包的密封 .jar 中实例化一个类将失败。请参阅测试 SealedFail2()。
  4. 从密封的 .jar 中实例化一个对象只会加载(并密封)该特定类所在的包。不会同时加载同一 .jar 中的其他包。请参阅测试 SealedFail3()。
  5. 您可以从 .jar 中成功实例化在已密封和加载包的子包中定义的对象,而不会出现问题。请参阅测试 SubPackage()。

关于java - 密封 .jar 时会密封哪些特定包?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42423695/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com