Skip to content

Commit b752c2f

Browse files
BEGIN_PUBLIC (#18729)
PR #18406: Teach ijar about dynamic constants. Imported from GitHub PR #18406 END_PUBLIC PiperOrigin-RevId: 540750474 Change-Id: If61bcaaf018b92a1bf87335c1075c28294932b1f Co-authored-by: Benjamin Peterson <[email protected]>
1 parent ac0f830 commit b752c2f

File tree

4 files changed

+150
-21
lines changed

4 files changed

+150
-21
lines changed

third_party/ijar/classfile.cc

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -53,22 +53,23 @@ std::string ToString(const T& value) {
5353

5454
namespace devtools_ijar {
5555

56-
// See Table 4.3 in JVM Spec.
56+
// See Table 4.4 in JVM 17 Spec.
5757
enum CONSTANT {
58-
CONSTANT_Class = 7,
59-
CONSTANT_FieldRef = 9,
60-
CONSTANT_Methodref = 10,
58+
CONSTANT_Class = 7,
59+
CONSTANT_FieldRef = 9,
60+
CONSTANT_Methodref = 10,
6161
CONSTANT_Interfacemethodref = 11,
62-
CONSTANT_String = 8,
63-
CONSTANT_Integer = 3,
64-
CONSTANT_Float = 4,
65-
CONSTANT_Long = 5,
66-
CONSTANT_Double = 6,
67-
CONSTANT_NameAndType = 12,
68-
CONSTANT_Utf8 = 1,
69-
CONSTANT_MethodHandle = 15,
70-
CONSTANT_MethodType = 16,
71-
CONSTANT_InvokeDynamic = 18
62+
CONSTANT_String = 8,
63+
CONSTANT_Integer = 3,
64+
CONSTANT_Float = 4,
65+
CONSTANT_Long = 5,
66+
CONSTANT_Double = 6,
67+
CONSTANT_NameAndType = 12,
68+
CONSTANT_Utf8 = 1,
69+
CONSTANT_MethodHandle = 15,
70+
CONSTANT_MethodType = 16,
71+
CONSTANT_Dynamic = 17,
72+
CONSTANT_InvokeDynamic = 18
7273
};
7374

7475
// See Tables 4.1, 4.4, 4.5 in JVM Spec.
@@ -390,12 +391,32 @@ struct Constant_MethodType : Constant
390391
};
391392

392393
// See sec.4.4.10 of JVM spec.
393-
struct Constant_InvokeDynamic : Constant
394-
{
395-
Constant_InvokeDynamic(u2 bootstrap_method_attr_index, u2 name_and_type_index) :
396-
Constant(CONSTANT_InvokeDynamic),
397-
bootstrap_method_attr_index_(bootstrap_method_attr_index),
398-
name_and_type_index_(name_and_type_index) {}
394+
struct Constant_Dynamic : Constant {
395+
Constant_Dynamic(u2 bootstrap_method_attr_index, u2 name_and_type_index)
396+
: Constant(CONSTANT_Dynamic),
397+
bootstrap_method_attr_index_(bootstrap_method_attr_index),
398+
name_and_type_index_(name_and_type_index) {}
399+
400+
void Write(u1 *&p) {
401+
put_u1(p, tag_);
402+
put_u2be(p, bootstrap_method_attr_index_);
403+
put_u2be(p, name_and_type_index_);
404+
}
405+
406+
std::string Display() {
407+
return "Constant_Dynamic::" + ToString(bootstrap_method_attr_index_) +
408+
"::" + constant(name_and_type_index_)->Display();
409+
}
410+
411+
u2 bootstrap_method_attr_index_;
412+
u2 name_and_type_index_;
413+
};
414+
415+
struct Constant_InvokeDynamic : Constant {
416+
Constant_InvokeDynamic(u2 bootstrap_method_attr_index, u2 name_and_type_index)
417+
: Constant(CONSTANT_InvokeDynamic),
418+
bootstrap_method_attr_index_(bootstrap_method_attr_index),
419+
name_and_type_index_(name_and_type_index) {}
399420

400421
void Write(u1 *&p) {
401422
put_u1(p, tag_);
@@ -1650,6 +1671,13 @@ bool ClassFile::ReadConstantPool(const u1 *&p) {
16501671
const_pool_in.push_back(new Constant_MethodType(descriptor_index));
16511672
break;
16521673
}
1674+
case CONSTANT_Dynamic: {
1675+
u2 bootstrap_method_attr = get_u2be(p);
1676+
u2 name_name_type_index = get_u2be(p);
1677+
const_pool_in.push_back(
1678+
new Constant_Dynamic(bootstrap_method_attr, name_name_type_index));
1679+
break;
1680+
}
16531681
case CONSTANT_InvokeDynamic: {
16541682
u2 bootstrap_method_attr = get_u2be(p);
16551683
u2 name_name_type_index = get_u2be(p);
@@ -1658,7 +1686,7 @@ bool ClassFile::ReadConstantPool(const u1 *&p) {
16581686
break;
16591687
}
16601688
default: {
1661-
fprintf(stderr, "Unknown constant: %02x. Passing class through.\n",
1689+
fprintf(stderr, "Unknown constant: %hhu. Passing class through.\n",
16621690
tag);
16631691
return false;
16641692
}

third_party/ijar/test/BUILD

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ sh_test(
4646
# Intentionally bad test JAR: file count in central directory
4747
# wrong.
4848
"libwrongcentraldir.jar",
49+
":dynamic_constant.jar",
4950
"@bazel_tools//tools/jdk:current_java_runtime",
5051
],
5152
shard_count = 5,
@@ -204,6 +205,21 @@ genrule(
204205
tools = ["gen_source_debug_extension"],
205206
)
206207

208+
java_binary(
209+
name = "gen_dynamic_constant",
210+
srcs = ["GenDynamicConstant.java"],
211+
main_class = "test.GenDynamicConstant",
212+
deps = ["//third_party:asm"],
213+
)
214+
215+
genrule(
216+
name = "gen_dynamic_constant_jar",
217+
srcs = [],
218+
outs = ["dynamic_constant.jar"],
219+
cmd = "$(location :gen_dynamic_constant) $@",
220+
tools = [":gen_dynamic_constant"],
221+
)
222+
207223
java_library(
208224
name = "local_and_anonymous_lib",
209225
srcs = ["LocalAndAnonymous.java"],
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Copyright 2023 The Bazel Authors. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package test;
16+
17+
import java.io.FileOutputStream;
18+
import java.io.IOException;
19+
import java.lang.invoke.ConstantBootstraps;
20+
import java.util.jar.JarOutputStream;
21+
import java.util.zip.ZipEntry;
22+
import org.objectweb.asm.ClassWriter;
23+
import org.objectweb.asm.ConstantDynamic;
24+
import org.objectweb.asm.Handle;
25+
import org.objectweb.asm.MethodVisitor;
26+
import org.objectweb.asm.Opcodes;
27+
import org.objectweb.asm.Type;
28+
29+
public class GenDynamicConstant {
30+
public static void main(String[] args) throws IOException {
31+
try (JarOutputStream jos = new JarOutputStream(new FileOutputStream(args[0]))) {
32+
jos.putNextEntry(new ZipEntry("dynamicconstant/Test.class"));
33+
jos.write(dump());
34+
}
35+
}
36+
37+
public static byte[] dump() {
38+
ClassWriter cw = new ClassWriter(0);
39+
MethodVisitor mv;
40+
41+
cw.visit(
42+
Opcodes.V16,
43+
Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER,
44+
"dynamicconstant/Test",
45+
null,
46+
"java/lang/Object",
47+
null);
48+
49+
cw.visitEnd();
50+
51+
var desc = Type.INT_TYPE.getDescriptor();
52+
var get =
53+
cw.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "get", "()" + desc, null, null);
54+
get.visitInsn(Opcodes.ICONST_5);
55+
get.visitInsn(Opcodes.IRETURN);
56+
get.visitMaxs(1, 0);
57+
get.visitEnd();
58+
var invokeHandle =
59+
new Handle(
60+
Opcodes.H_INVOKESTATIC,
61+
Type.getInternalName(ConstantBootstraps.class),
62+
"invoke",
63+
"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/invoke/MethodHandle;[Ljava/lang/Object;)Ljava/lang/Object;",
64+
false);
65+
var handle =
66+
new Handle(Opcodes.H_INVOKESTATIC, "dynamicconstant/Test", "get", "()" + desc, false);
67+
var run =
68+
cw.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "run", "()" + desc, null, null);
69+
run.visitLdcInsn(new ConstantDynamic("const", desc, invokeHandle, handle));
70+
run.visitInsn(Opcodes.IRETURN);
71+
run.visitMaxs(1, 0);
72+
run.visitEnd();
73+
74+
return cw.toByteArray();
75+
}
76+
}

third_party/ijar/test/ijar_test.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ CENTRAL_DIR_LARGEST_REGULAR=$IJAR_SRCDIR/test/largest_regular.jar
8585
CENTRAL_DIR_SMALLEST_ZIP64=$IJAR_SRCDIR/test/smallest_zip64.jar
8686
CENTRAL_DIR_ZIP64=$IJAR_SRCDIR/test/definitely_zip64.jar
8787
KEEP_FOR_COMPILE=$IJAR_SRCDIR/test/keep_for_compile_lib.jar
88+
DYNAMICCONSTANT_JAR=$IJAR_SRCDIR/test/dynamic_constant.jar
89+
DYNAMICCONSTANT_IJAR=$TEST_TMPDIR/dynamic_constant_interface.jar
8890

8991
#### Setup
9092

@@ -522,6 +524,13 @@ function test_method_parameters_attribute() {
522524
expect_log "MethodParameters" "MethodParameters not preserved!"
523525
}
524526

527+
function test_dynamic_constant() {
528+
$IJAR $DYNAMICCONSTANT_JAR $DYNAMICCONSTANT_IJAR || fail "ijar failed"
529+
530+
lines=$($JAVAP -c -private -classpath $DYNAMICCONSTANT_IJAR dynamicconstant.Test | grep -c Code: || true)
531+
check_eq 0 $lines "Interface jar should have no method bodies!"
532+
}
533+
525534
function test_nestmates_attribute() {
526535
# Check that Java 11 NestMates attributes are preserved
527536
$IJAR $NESTMATES_JAR $NESTMATES_IJAR || fail "ijar failed"

0 commit comments

Comments
 (0)