* @param classSpec the class spec
* @param resourceLoader the resource loader of the class spec
* @return the new class
*/
private Class<?> defineClass(final String name, final ClassSpec classSpec, final ResourceLoader resourceLoader) {
final ModuleLogger log = Module.log;
final Module module = this.module;
log.trace("Attempting to define class %s in %s", name, module);
// Ensure that the package is loaded
final int lastIdx = name.lastIndexOf('.');
if (lastIdx != -1) {
// there's a package name; get the Package for it
final String packageName = name.substring(0, lastIdx);
synchronized (this) {
Package pkg = findLoadedPackage(packageName);
if (pkg == null) {
try {
pkg = definePackage(packageName, resourceLoader.getPackageSpec(packageName));
} catch (IOException e) {
pkg = definePackage(packageName, null);
}
}
// Check sealing
if (pkg.isSealed() && ! pkg.isSealed(classSpec.getCodeSource().getLocation())) {
log.trace("Detected a sealing violation (attempt to define class %s in sealed package %s in %s)", name, packageName, module);
// use the same message as the JDK
throw new SecurityException("sealing violation: package " + packageName + " is sealed");
}
}
}
final Class<?> newClass;
try {
byte[] bytes = classSpec.getBytes();
try {
final ProtectionDomain protectionDomain = getProtectionDomain(classSpec.getCodeSource());
if (transformer != null) {
try {
bytes = transformer.transform(this, name.replace('.', '/'), null, protectionDomain, bytes);
} catch (Exception e) {
ClassFormatError error = new ClassFormatError(e.getMessage());
error.initCause(e);
throw error;
}
}
final long start = Metrics.getCurrentCPUTime();
newClass = doDefineOrLoadClass(name, bytes, 0, bytes.length, protectionDomain);
module.getModuleLoader().addClassLoadTime(Metrics.getCurrentCPUTime() - start);
log.classDefined(name, module);
} catch (NoClassDefFoundError e) {
// Prepend the current class name, so that transitive class definition issues are clearly expressed
final LinkageError ne = new LinkageError("Failed to link " + name.replace('.', '/') + " (" + module + ")");
ne.initCause(e);
throw ne;
}
} catch (Error e) {
log.classDefineFailed(e, name, module);
throw e;
} catch (RuntimeException e) {
log.classDefineFailed(e, name, module);
throw e;
}
final AssertionSetting setting = classSpec.getAssertionSetting();
if (setting != AssertionSetting.INHERIT) {
setClassAssertionStatus(name, setting == AssertionSetting.ENABLED);