Skip to content

Commit

Permalink
Gracefully handle absence of Unsafe.defineAnonymousClass (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
szegedi committed Jun 29, 2021
1 parent d577a18 commit f18c55b
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ private static final class AnonymousContextCodeInstaller extends ContextCodeInst
private static final MethodHandle DEFINE_ANONYMOUS_CLASS = getDefineAnonymousClass();
private static final String ANONYMOUS_HOST_CLASS_NAME = Compiler.SCRIPTS_PACKAGE.replace('/', '.') + ".AnonymousHost";
private static final byte[] ANONYMOUS_HOST_CLASS_BYTES = getAnonymousHostClassBytes();
static volatile Exception initFailure;

private final Class<?> hostClass;

Expand All @@ -331,8 +332,9 @@ private static MethodHandle getDefineAnonymousClass() {
final Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
return mh.bindTo(f.get(null));
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e);
} catch (Exception e) {
initFailure = e;
return null;
}
});
}
Expand Down Expand Up @@ -1501,8 +1503,9 @@ private synchronized Class<?> compile(final Source source, final ErrorManager er
final URL url = source.getURL();
final CodeSource cs = new CodeSource(url, (CodeSigner[])null);
final CodeInstaller installer;
if (!env.useAnonymousClasses(source.getLength()) || env._persistent_cache || !env._lazy_compilation) {
// Persistent code cache and eager compilation preclude use of VM anonymous classes
if (env._persistent_cache || !env._lazy_compilation || !env.useAnonymousClasses(source.getLength(), () -> AnonymousContextCodeInstaller.initFailure) ) {
// Persistent code cache, eager compilation, or inability to use Unsafe.defineAnonymousClass (typically, JDK 17+)
// preclude use of VM anonymous classes
final ScriptLoader loader = env._loader_per_compile ? createNewLoader() : scriptLoader;
installer = new NamedContextCodeInstaller(this, cs, loader);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.StringTokenizer;
import java.util.TimeZone;
import java.util.function.Supplier;
import java.util.logging.Level;
import org.openjdk.nashorn.internal.codegen.Namespace;
import org.openjdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
Expand Down Expand Up @@ -225,7 +227,7 @@ public enum FunctionStatementBehavior {
/** Timing */
public final Timing _timing;

/** Whether to use anonymous classes. See {@link #useAnonymousClasses(int)}. */
/** Whether to use anonymous classes. See {@link #useAnonymousClasses(int, Supplier)}. */
private final AnonymousClasses _anonymousClasses;
private enum AnonymousClasses {
AUTO,
Expand Down Expand Up @@ -477,9 +479,16 @@ public boolean isTimingEnabled() {
* @param sourceLength length of source being compiled.
* @return true if anonymous classes should be used
*/
public boolean useAnonymousClasses(final int sourceLength) {
return _anonymousClasses == AnonymousClasses.ON
|| (_anonymousClasses == AnonymousClasses.AUTO && sourceLength <= _anonymous_classes_threshold);
public boolean useAnonymousClasses(final int sourceLength, Supplier<Exception> anonymousInitFailure) {
if (_anonymousClasses == AnonymousClasses.ON) {
Optional.ofNullable(anonymousInitFailure.get()).ifPresent(e -> {
throw new IllegalStateException("Can not use anonymous class loading", e);
});
return true;
}
return _anonymousClasses == AnonymousClasses.AUTO &&
sourceLength <= _anonymous_classes_threshold &&
anonymousInitFailure.get() == null;
}

}

0 comments on commit f18c55b

Please sign in to comment.