8263108: Class initialization deadlock in java.lang.constant

Reviewed-by: vtewari, plevart, chegar
This commit is contained in:
Jaikiran Pai 2021-03-18 01:45:07 +00:00
parent 5d5813a5d3
commit 9225a23023
2 changed files with 171 additions and 11 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -64,15 +64,6 @@ public abstract class DynamicConstantDesc<T>
private final String constantName;
private final ClassDesc constantType;
private static final Map<MethodHandleDesc, Function<DynamicConstantDesc<?>, ConstantDesc>> canonicalMap
= Map.ofEntries(Map.entry(ConstantDescs.BSM_PRIMITIVE_CLASS, DynamicConstantDesc::canonicalizePrimitiveClass),
Map.entry(ConstantDescs.BSM_ENUM_CONSTANT, DynamicConstantDesc::canonicalizeEnum),
Map.entry(ConstantDescs.BSM_NULL_CONSTANT, DynamicConstantDesc::canonicalizeNull),
Map.entry(ConstantDescs.BSM_VARHANDLE_STATIC_FIELD, DynamicConstantDesc::canonicalizeStaticFieldVarHandle),
Map.entry(ConstantDescs.BSM_VARHANDLE_FIELD, DynamicConstantDesc::canonicalizeFieldVarHandle),
Map.entry(ConstantDescs.BSM_VARHANDLE_ARRAY, DynamicConstantDesc::canonicalizeArrayVarHandle)
);
/**
* Creates a nominal descriptor for a dynamic constant.
*
@ -137,6 +128,8 @@ public abstract class DynamicConstantDesc<T>
* format
* @jvms 4.2.2 Unqualified Names
*/
// Do not call this method from the static initialization of java.lang.constant.ConstantDescs
// since that can lead to potential deadlock during multi-threaded concurrent execution
public static<T> ConstantDesc ofCanonical(DirectMethodHandleDesc bootstrapMethod,
String constantName,
ClassDesc constantType,
@ -281,7 +274,7 @@ public abstract class DynamicConstantDesc<T>
}
private ConstantDesc tryCanonicalize() {
Function<DynamicConstantDesc<?>, ConstantDesc> f = canonicalMap.get(bootstrapMethod);
Function<DynamicConstantDesc<?>, ConstantDesc> f = CanonicalMapHolder.CANONICAL_MAP.get(bootstrapMethod);
if (f != null) {
try {
return f.apply(this);
@ -394,4 +387,15 @@ public abstract class DynamicConstantDesc<T>
super(bootstrapMethod, constantName, constantType, bootstrapArgs);
}
}
private static final class CanonicalMapHolder {
static final Map<MethodHandleDesc, Function<DynamicConstantDesc<?>, ConstantDesc>> CANONICAL_MAP =
Map.ofEntries(
Map.entry(ConstantDescs.BSM_PRIMITIVE_CLASS, DynamicConstantDesc::canonicalizePrimitiveClass),
Map.entry(ConstantDescs.BSM_ENUM_CONSTANT, DynamicConstantDesc::canonicalizeEnum),
Map.entry(ConstantDescs.BSM_NULL_CONSTANT, DynamicConstantDesc::canonicalizeNull),
Map.entry(ConstantDescs.BSM_VARHANDLE_STATIC_FIELD, DynamicConstantDesc::canonicalizeStaticFieldVarHandle),
Map.entry(ConstantDescs.BSM_VARHANDLE_FIELD, DynamicConstantDesc::canonicalizeFieldVarHandle),
Map.entry(ConstantDescs.BSM_VARHANDLE_ARRAY, DynamicConstantDesc::canonicalizeArrayVarHandle));
}
}