mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8336777: BufferedMethodBuilder not initialized with static flag
Reviewed-by: asotona
This commit is contained in:
parent
c25c4896ad
commit
3ade2b6114
6 changed files with 102 additions and 11 deletions
|
@ -25,6 +25,7 @@
|
||||||
package jdk.internal.classfile.impl;
|
package jdk.internal.classfile.impl;
|
||||||
|
|
||||||
import java.lang.constant.MethodTypeDesc;
|
import java.lang.constant.MethodTypeDesc;
|
||||||
|
import java.lang.reflect.AccessFlag;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
@ -44,7 +45,7 @@ import java.lang.classfile.MethodModel;
|
||||||
import java.lang.classfile.constantpool.Utf8Entry;
|
import java.lang.classfile.constantpool.Utf8Entry;
|
||||||
|
|
||||||
public final class BufferedMethodBuilder
|
public final class BufferedMethodBuilder
|
||||||
implements TerminalMethodBuilder, MethodInfo {
|
implements TerminalMethodBuilder {
|
||||||
private final List<MethodElement> elements;
|
private final List<MethodElement> elements;
|
||||||
private final SplitConstantPool constantPool;
|
private final SplitConstantPool constantPool;
|
||||||
private final ClassFileImpl context;
|
private final ClassFileImpl context;
|
||||||
|
@ -59,23 +60,32 @@ public final class BufferedMethodBuilder
|
||||||
ClassFileImpl context,
|
ClassFileImpl context,
|
||||||
Utf8Entry nameInfo,
|
Utf8Entry nameInfo,
|
||||||
Utf8Entry typeInfo,
|
Utf8Entry typeInfo,
|
||||||
|
int flags,
|
||||||
MethodModel original) {
|
MethodModel original) {
|
||||||
this.elements = new ArrayList<>();
|
this.elements = new ArrayList<>();
|
||||||
this.constantPool = constantPool;
|
this.constantPool = constantPool;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.name = nameInfo;
|
this.name = nameInfo;
|
||||||
this.desc = typeInfo;
|
this.desc = typeInfo;
|
||||||
this.flags = AccessFlags.ofMethod();
|
this.flags = AccessFlags.ofMethod(flags);
|
||||||
this.original = original;
|
this.original = original;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MethodBuilder with(MethodElement element) {
|
public MethodBuilder with(MethodElement element) {
|
||||||
elements.add(element);
|
elements.add(element);
|
||||||
if (element instanceof AccessFlags f) this.flags = f;
|
if (element instanceof AccessFlags f) this.flags = checkFlags(f);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private AccessFlags checkFlags(AccessFlags updated) {
|
||||||
|
boolean wasStatic = updated.has(AccessFlag.STATIC);
|
||||||
|
boolean isStatic = flags.has(AccessFlag.STATIC);
|
||||||
|
if (wasStatic != isStatic)
|
||||||
|
throw new IllegalArgumentException("Cannot change ACC_STATIC flag of method");
|
||||||
|
return updated;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConstantPoolBuilder constantPool() {
|
public ConstantPoolBuilder constantPool() {
|
||||||
return constantPool;
|
return constantPool;
|
||||||
|
|
|
@ -79,7 +79,7 @@ public final class ChainedClassBuilder
|
||||||
public ClassBuilder withMethod(Utf8Entry name, Utf8Entry descriptor, int flags,
|
public ClassBuilder withMethod(Utf8Entry name, Utf8Entry descriptor, int flags,
|
||||||
Consumer<? super MethodBuilder> handler) {
|
Consumer<? super MethodBuilder> handler) {
|
||||||
consumer.accept(new BufferedMethodBuilder(terminal.constantPool, terminal.context,
|
consumer.accept(new BufferedMethodBuilder(terminal.constantPool, terminal.context,
|
||||||
name, descriptor, null)
|
name, descriptor, flags, null)
|
||||||
.run(handler)
|
.run(handler)
|
||||||
.toModel());
|
.toModel());
|
||||||
return this;
|
return this;
|
||||||
|
@ -88,7 +88,7 @@ public final class ChainedClassBuilder
|
||||||
@Override
|
@Override
|
||||||
public ClassBuilder transformMethod(MethodModel method, MethodTransform transform) {
|
public ClassBuilder transformMethod(MethodModel method, MethodTransform transform) {
|
||||||
BufferedMethodBuilder builder = new BufferedMethodBuilder(terminal.constantPool, terminal.context,
|
BufferedMethodBuilder builder = new BufferedMethodBuilder(terminal.constantPool, terminal.context,
|
||||||
method.methodName(), method.methodType(), method);
|
method.methodName(), method.methodType(), method.flags().flagsMask(), method);
|
||||||
builder.transform(method, transform);
|
builder.transform(method, transform);
|
||||||
consumer.accept(builder.toModel());
|
consumer.accept(builder.toModel());
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -42,7 +42,7 @@ import java.lang.classfile.constantpool.Utf8Entry;
|
||||||
|
|
||||||
public final class DirectMethodBuilder
|
public final class DirectMethodBuilder
|
||||||
extends AbstractDirectBuilder<MethodModel>
|
extends AbstractDirectBuilder<MethodModel>
|
||||||
implements TerminalMethodBuilder, WritableElement<MethodModel>, MethodInfo {
|
implements TerminalMethodBuilder, WritableElement<MethodModel> {
|
||||||
|
|
||||||
final Utf8Entry name;
|
final Utf8Entry name;
|
||||||
final Utf8Entry desc;
|
final Utf8Entry desc;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -29,7 +29,8 @@ import java.lang.classfile.constantpool.Utf8Entry;
|
||||||
|
|
||||||
import static java.lang.classfile.ClassFile.ACC_STATIC;
|
import static java.lang.classfile.ClassFile.ACC_STATIC;
|
||||||
|
|
||||||
public interface MethodInfo {
|
public sealed interface MethodInfo
|
||||||
|
permits MethodImpl, TerminalMethodBuilder, BufferedMethodBuilder.Model {
|
||||||
Utf8Entry methodName();
|
Utf8Entry methodName();
|
||||||
Utf8Entry methodType();
|
Utf8Entry methodType();
|
||||||
MethodTypeDesc methodTypeSymbol();
|
MethodTypeDesc methodTypeSymbol();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -28,7 +28,7 @@ import java.lang.classfile.CodeModel;
|
||||||
import java.lang.classfile.MethodBuilder;
|
import java.lang.classfile.MethodBuilder;
|
||||||
|
|
||||||
public sealed interface TerminalMethodBuilder
|
public sealed interface TerminalMethodBuilder
|
||||||
extends MethodBuilder
|
extends MethodBuilder, MethodInfo
|
||||||
permits BufferedMethodBuilder, DirectMethodBuilder {
|
permits BufferedMethodBuilder, DirectMethodBuilder {
|
||||||
BufferedCodeBuilder bufferedCodeBuilder(CodeModel original);
|
BufferedCodeBuilder bufferedCodeBuilder(CodeModel original);
|
||||||
}
|
}
|
||||||
|
|
80
test/jdk/jdk/classfile/MethodBuilderStaticFlagTest.java
Normal file
80
test/jdk/jdk/classfile/MethodBuilderStaticFlagTest.java
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024, 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
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import jdk.internal.classfile.impl.ChainedClassBuilder;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.lang.classfile.ClassBuilder;
|
||||||
|
import java.lang.classfile.ClassElement;
|
||||||
|
import java.lang.classfile.ClassFile;
|
||||||
|
import java.lang.classfile.ClassTransform;
|
||||||
|
import java.lang.constant.ClassDesc;
|
||||||
|
|
||||||
|
import static java.lang.classfile.ClassFile.ACC_PUBLIC;
|
||||||
|
import static java.lang.classfile.ClassFile.ACC_STATIC;
|
||||||
|
import static java.lang.constant.ConstantDescs.MTD_void;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 8336777
|
||||||
|
* @summary Testing MethodBuilder correctly rejecting resetting the static
|
||||||
|
* access flag.
|
||||||
|
* @run junit MethodBuilderStaticFlagTest
|
||||||
|
*/
|
||||||
|
class MethodBuilderStaticFlagTest {
|
||||||
|
|
||||||
|
void testClassBuilder(ClassBuilder clb) {
|
||||||
|
clb.withMethod("staticToStatic", MTD_void, ACC_STATIC, mb -> mb.withFlags(ACC_PUBLIC | ACC_STATIC));
|
||||||
|
assertThrows(IllegalArgumentException.class, () ->
|
||||||
|
clb.withMethod("staticToInstance", MTD_void, ACC_STATIC, mb -> mb.withFlags(ACC_PUBLIC)));
|
||||||
|
assertThrows(IllegalArgumentException.class, () ->
|
||||||
|
clb.withMethod("instanceToStatic", MTD_void, 0, mb -> mb.withFlags(ACC_PUBLIC | ACC_STATIC)));
|
||||||
|
clb.withMethod("instanceToInstance", MTD_void, 0, mb -> mb.withFlags(ACC_PUBLIC));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDirectBuilder() {
|
||||||
|
ClassFile.of().build(ClassDesc.of("C1"), this::testClassBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testBufferedBuilder() {
|
||||||
|
var cf = ClassFile.of();
|
||||||
|
var bytes = cf.build(ClassDesc.of("C2"), _ -> {});
|
||||||
|
var cm = cf.parse(bytes);
|
||||||
|
|
||||||
|
cf.transformClass(cm, new ClassTransform() {
|
||||||
|
@Override
|
||||||
|
public void accept(ClassBuilder builder, ClassElement element) {
|
||||||
|
builder.with(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void atEnd(ClassBuilder clb) {
|
||||||
|
assertInstanceOf(ChainedClassBuilder.class, clb);
|
||||||
|
testClassBuilder(clb);
|
||||||
|
}
|
||||||
|
}.andThen(ClassBuilder::with));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue