Skip to content

Commit b67d996

Browse files
YaaZjbrbot
authored andcommitted
JBR-9552 Isolated JBR API context per classloader
1 parent b01f939 commit b67d996

File tree

16 files changed

+303
-241
lines changed

16 files changed

+303
-241
lines changed

make/common/JavaCompilation.gmk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ define SetupJavaCompilationBody
304304

305305
ifeq ($$($1_PROCESS_JBR_API), true)
306306
# Automatic path conversion doesn't work for two arguments, so call fixpath manually
307-
$1_JBR_API_FLAGS := -Xplugin:"jbr-api $$(call FixPath, $$($1_BIN)/java.base/META-INF/jbrapi.registry) $$(call FixPath, $(TOPDIR)/jb/jbr-api.version)"
307+
$1_JBR_API_FLAGS := -Xplugin:"jbr-api $$(call FixPath, $$($1_BIN)/java.base/META-INF/jbrapi) $$(call FixPath, $(TOPDIR)/jb/jbr-api.version)"
308308
$1_EXTRA_DEPS := $$($1_EXTRA_DEPS) $$(BUILDTOOLS_OUTPUTDIR)/plugins/_the.COMPILE_JBR_API_PLUGIN_batch
309309
endif
310310

make/jdk/src/classes/build/tools/jbrapi/JBRApiPlugin.java

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -198,34 +198,35 @@ List<String> addBindings() {
198198
return unresolvedErrors;
199199
}
200200

201-
void read(RandomAccessFile file) throws IOException {
201+
void read(RandomAccessFile file, boolean internal) throws IOException {
202202
String s;
203203
while ((s = file.readLine()) != null) {
204204
String[] tokens = s.split(" ");
205205
switch (tokens[0]) {
206-
case "TYPE" -> {
207-
types.put(tokens[1], new Type(tokens[2], Binding.valueOf(tokens[3])));
208-
if (tokens.length > 4 && tokens[4].equals("INTERNAL")) internal.add(tokens[1]);
209-
}
206+
case "VERSION" -> {}
210207
case "STATIC" -> {
211208
StaticDescriptor descriptor = new StaticDescriptor(new StaticMethod(
212209
tokens[1], tokens[2]), tokens[3]);
213210
methods.put(descriptor, new StaticMethod(tokens[4], tokens[5]));
214-
if (tokens.length > 6 && tokens[6].equals("INTERNAL")) internal.add(descriptor);
211+
if (internal) this.internal.add(descriptor);
212+
}
213+
default -> {
214+
types.put(tokens[1], new Type(tokens[2], Binding.valueOf(tokens[0])));
215+
if (internal) this.internal.add(tokens[1]);
215216
}
216217
}
217218
}
218219
}
219220

220-
void write(RandomAccessFile file) throws IOException {
221+
void write(RandomAccessFile pub, RandomAccessFile priv) throws IOException {
221222
for (var t : types.entrySet()) {
222-
file.writeBytes("TYPE " + t.getKey() + " " + t.getValue().type + " " + t.getValue().binding +
223-
(internal.contains(t.getKey()) ? " INTERNAL\n" : "\n"));
223+
(internal.contains(t.getKey()) ? priv : pub).writeBytes(
224+
t.getValue().binding + " " + t.getKey() + " " + t.getValue().type + "\n");
224225
}
225226
for (var t : methods.entrySet()) {
226-
file.writeBytes("STATIC " + t.getKey().method.type + " " + t.getKey().method.name + " " +
227-
t.getKey().descriptor + " " + t.getValue().type + " " + t.getValue().name +
228-
(internal.contains(t.getKey()) ? " INTERNAL\n" : "\n"));
227+
(internal.contains(t.getKey()) ? priv : pub).writeBytes(
228+
"STATIC " + t.getKey().method.type + " " + t.getKey().method.name + " " +
229+
t.getKey().descriptor + " " + t.getValue().type + " " + t.getValue().name + "\n");
229230
}
230231
}
231232
}
@@ -399,7 +400,7 @@ public String getName() {
399400

400401
@Override
401402
public void init(JavacTask jt, String... args) {
402-
Path output = Path.of(args[0]);
403+
Path pubPath = Path.of(args[0] + ".public"), privPath = Path.of(args[0] + ".private");
403404
String implVersion;
404405
try {
405406
implVersion = Files.readString(Path.of(args[1])).strip();
@@ -426,18 +427,21 @@ public Void scan(Element e, CompilationUnitTree root) {
426427
}
427428
}.scan(te.getTypeElement(), te.getCompilationUnit());
428429
} else if (te.getKind() == TaskEvent.Kind.COMPILATION) {
429-
try (RandomAccessFile file = new RandomAccessFile(output.toFile(), "rw");
430-
FileChannel channel = file.getChannel()) {
430+
try (RandomAccessFile pub = new RandomAccessFile(pubPath.toFile(), "rw");
431+
RandomAccessFile priv = new RandomAccessFile(privPath.toFile(), "rw");
432+
FileChannel channel = pub.getChannel()) {
431433
for (;;) {
432434
try { if (channel.lock() != null) break; } catch (OverlappingFileLockException ignore) {}
433435
LockSupport.parkNanos(10_000000);
434436
}
435437
Registry r = new Registry();
436-
r.read(file);
438+
r.read(pub, false);
439+
r.read(priv, true);
437440
var unresolvedErrors = r.addBindings();
438-
file.setLength(0);
439-
file.writeBytes("VERSION " + implVersion + "\n");
440-
r.write(file);
441+
priv.setLength(0);
442+
pub.setLength(0);
443+
pub.writeBytes("VERSION " + implVersion + "\n");
444+
r.write(pub, priv);
441445
if (!unresolvedErrors.isEmpty()) {
442446
throw new RuntimeException(String.join("\n", unresolvedErrors));
443447
}

src/java.base/share/classes/com/jetbrains/bootstrap/JBRApiBootstrap.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,7 @@ private JBRApiBootstrap() {}
4545
* @return implementation for {@link com.jetbrains.JBR.ServiceApi} interface
4646
*/
4747
public static synchronized Object bootstrap(MethodHandles.Lookup outerLookup) {
48-
if (!JBRApi.ENABLED) return null;
49-
if (JBRApi.VERBOSE) {
50-
System.out.println("JBR API bootstrap in compatibility mode: Object bootstrap(MethodHandles.Lookup)");
51-
}
48+
System.out.println("JBR API bootstrap in compatibility mode: Object bootstrap(MethodHandles.Lookup)");
5249
Class<?> apiInterface;
5350
try {
5451
apiInterface = outerLookup.findClass("com.jetbrains.JBR$ServiceApi");

src/java.base/share/classes/com/jetbrains/exported/JBRApiSupport.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,22 +52,20 @@ private JBRApiSupport() {}
5252
* @param extensionExtractor receives method, returns its extension enum, or null
5353
* @return implementation for {@code JBR.ServiceApi} interface
5454
*/
55-
@SuppressWarnings("rawtypes")
5655
public static synchronized Object bootstrap(Class<?> apiInterface,
5756
Class<? extends Annotation> serviceAnnotation,
5857
Class<? extends Annotation> providedAnnotation,
5958
Class<? extends Annotation> providesAnnotation,
60-
Map<Enum<?>, Class[]> knownExtensions,
59+
Map<Enum<?>, Class<?>[]> knownExtensions,
6160
Function<Method, Enum<?>> extensionExtractor) {
62-
if (!JBRApi.ENABLED) return null;
63-
JBRApi.init(
61+
return JBRApi.init(
6462
null,
63+
apiInterface,
6564
serviceAnnotation,
6665
providedAnnotation,
6766
providesAnnotation,
6867
knownExtensions,
6968
extensionExtractor);
70-
return JBRApi.getService(apiInterface);
7169
}
7270

7371
/**

src/java.base/share/classes/com/jetbrains/internal/jbrapi/AccessContext.java

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,21 +46,29 @@
4646
*/
4747
class AccessContext {
4848

49+
static final int DYNAMIC_CALL_TARGET_NAME_OFFSET = 128;
50+
@SuppressWarnings("unchecked")
51+
static Supplier<MethodHandle>[] getDynamicCallTargets(Lookup target) {
52+
try {
53+
return (Supplier<MethodHandle>[]) target.findStaticVarHandle(
54+
target.lookupClass(), "dynamicCallTargets", Supplier[].class).get();
55+
} catch (NoSuchFieldException | IllegalAccessException e) {
56+
throw new RuntimeException(e);
57+
}
58+
}
4959
private static final DirectMethodHandleDesc BOOTSTRAP_DYNAMIC_DESC = MethodHandleDesc.ofMethod(
5060
DirectMethodHandleDesc.Kind.STATIC, desc(JBRApiSupport.class), "bootstrapDynamic",
5161
desc(CallSite.class, Lookup.class, String.class, MethodType.class));
5262

5363
private final Map<Class<?>, Boolean> accessibleClasses = new HashMap<>();
5464
final Map<Proxy, Boolean> dependencies = new HashMap<>(); // true for required, false for optional
55-
final List<DynamicCallTarget> dynamicCallTargets = new ArrayList<>();
65+
final List<Supplier<MethodHandle>> dynamicCallTargets = new ArrayList<>();
5666
final Lookup caller;
5767

5868
AccessContext(Lookup caller) {
5969
this.caller = caller;
6070
}
6171

62-
record DynamicCallTarget(String name, MethodTypeDesc descriptor, Supplier<MethodHandle> futureHandle) {}
63-
6472
class Method {
6573
final CodeBuilder writer;
6674
private final boolean methodRequired;
@@ -84,10 +92,9 @@ void invokeDynamic(MethodHandle handle) {
8492
}
8593

8694
void invokeDynamic(MethodType type, Supplier<MethodHandle> futureHandle) {
87-
MethodTypeDesc desc = desc(erase(type));
88-
DynamicCallTarget t = new DynamicCallTarget("dynamic" + dynamicCallTargets.size(), desc, futureHandle);
89-
dynamicCallTargets.add(t);
90-
writer.invokedynamic(DynamicCallSiteDesc.of(BOOTSTRAP_DYNAMIC_DESC, t.name, desc));
95+
String name = String.valueOf((char) (dynamicCallTargets.size() + DYNAMIC_CALL_TARGET_NAME_OFFSET));
96+
dynamicCallTargets.add(futureHandle);
97+
writer.invokedynamic(DynamicCallSiteDesc.of(BOOTSTRAP_DYNAMIC_DESC, name, desc(erase(type))));
9198
}
9299

93100
void invokeDirect(MethodHandleInfo handleInfo) {

src/java.base/share/classes/com/jetbrains/internal/jbrapi/BytecodeUtils.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import java.lang.invoke.MethodType;
3838
import java.lang.reflect.Method;
3939
import java.util.function.Consumer;
40+
import java.util.function.Supplier;
4041

4142
import static java.lang.classfile.ClassFile.ACC_FINAL;
4243
import static java.lang.classfile.ClassFile.ACC_PUBLIC;
@@ -49,6 +50,8 @@ class BytecodeUtils {
4950
public static final ClassDesc VOID_DESC = desc(void.class);
5051
public static final ClassDesc OBJECT_DESC = desc(Object.class);
5152
public static final ClassDesc OBJECT_ARRAY_DESC = OBJECT_DESC.arrayType();
53+
public static final ClassDesc SUPPLIER_DESC = desc(Supplier.class);
54+
public static final ClassDesc SUPPLIER_ARRAY_DESC = SUPPLIER_DESC.arrayType();
5255
public static final ClassDesc EXTENSION_ARRAY_DESC = desc(long[].class);
5356
public static final ClassDesc PROXY_INTERFACE_DESC = desc(com.jetbrains.exported.JBRApiSupport.Proxy.class);
5457
public static final MethodTypeDesc GET_PROXY_TARGET_DESC = MethodTypeDesc.of(OBJECT_DESC);

0 commit comments

Comments
 (0)