Recognize JDK 11 nestmates attributes in ijar
http://cr.openjdk.java.net/~dlsmith/nestmates.html#jep181-4.7.28
http://cr.openjdk.java.net/~dlsmith/nestmates.html#jep181-4.7.29
Fixes: #5987
Related: #5723
PiperOrigin-RevId: 210393959
diff --git a/third_party/ijar/classfile.cc b/third_party/ijar/classfile.cc
index 5e163e3..b77e769 100644
--- a/third_party/ijar/classfile.cc
+++ b/third_party/ijar/classfile.cc
@@ -1190,6 +1190,48 @@
std::vector<MethodParameter*> parameters_;
};
+// See JVMS §4.7.28
+struct NestHostAttribute : Attribute {
+ static NestHostAttribute *Read(const u1 *&p, Constant *attribute_name,
+ u4 /*attribute_length*/) {
+ auto attr = new NestHostAttribute;
+ attr->attribute_name_ = attribute_name;
+ attr->host_class_index_ = constant(get_u2be(p));
+ return attr;
+ }
+
+ void Write(u1 *&p) {
+ WriteProlog(p, -1);
+ put_u2be(p, host_class_index_->slot());
+ }
+
+ Constant *host_class_index_;
+};
+
+// See JVMS §4.7.29
+struct NestMembersAttribute : Attribute {
+ static NestMembersAttribute *Read(const u1 *&p, Constant *attribute_name,
+ u4 /*attribute_length*/) {
+ auto attr = new NestMembersAttribute;
+ attr->attribute_name_ = attribute_name;
+ u2 number_of_classes = get_u2be(p);
+ for (int ii = 0; ii < number_of_classes; ++ii) {
+ attr->classes_.push_back(constant(get_u2be(p)));
+ }
+ return attr;
+ }
+
+ void Write(u1 *&p) {
+ WriteProlog(p, classes_.size() * 2 + 2);
+ put_u2be(p, classes_.size());
+ for (size_t ii = 0; ii < classes_.size(); ++ii) {
+ put_u2be(p, classes_[ii]->slot());
+ }
+ }
+
+ std::vector<Constant *> classes_;
+};
+
struct GeneralAttribute : Attribute {
static GeneralAttribute* Read(const u1 *&p, Constant *attribute_name,
u4 attribute_length) {
@@ -1399,6 +1441,12 @@
} else if (attr_name == "MethodParameters") {
attributes.push_back(
MethodParametersAttribute::Read(p, attribute_name, attribute_length));
+ } else if (attr_name == "NestHost") {
+ attributes.push_back(
+ NestHostAttribute::Read(p, attribute_name, attribute_length));
+ } else if (attr_name == "NestMembers") {
+ attributes.push_back(
+ NestMembersAttribute::Read(p, attribute_name, attribute_length));
} else {
// Skip over unknown attributes with a warning. The JVM spec
// says this is ok, so long as we handle the mandatory attributes.
diff --git a/third_party/ijar/test/BUILD b/third_party/ijar/test/BUILD
index 903d46e..7ab7608 100644
--- a/third_party/ijar/test/BUILD
+++ b/third_party/ijar/test/BUILD
@@ -31,6 +31,9 @@
"WellCompressed2.java",
":libtypeannotations2.jar",
":libmethodparameters.jar",
+ # This is a precompiled .jar file because it needs to be compiled with JDK 11.
+ # TODO(cushon): build from source once we have a JDK 11
+ "nestmates/nestmates.jar",
":source_debug_extension.jar",
":largest_regular.jar",
":smallest_zip64.jar",
diff --git a/third_party/ijar/test/ijar_test.sh b/third_party/ijar/test/ijar_test.sh
index 1a4959d..d7a5336 100755
--- a/third_party/ijar/test/ijar_test.sh
+++ b/third_party/ijar/test/ijar_test.sh
@@ -75,6 +75,8 @@
INVOKEDYNAMIC_IJAR=$TEST_TMPDIR/invokedynamic_interface.jar
METHODPARAM_JAR=$IJAR_SRCDIR/test/libmethodparameters.jar
METHODPARAM_IJAR=$TEST_TMPDIR/methodparameters_interface.jar
+NESTMATES_JAR=$IJAR_SRCDIR/test/nestmates/nestmates.jar
+NESTMATES_IJAR=$TEST_TMPDIR/nestmates_interface.jar
SOURCEDEBUGEXT_JAR=$IJAR_SRCDIR/test/source_debug_extension.jar
SOURCEDEBUGEXT_IJAR=$TEST_TMPDIR/source_debug_extension.jar
CENTRAL_DIR_LARGEST_REGULAR=$IJAR_SRCDIR/test/largest_regular.jar
@@ -516,6 +518,14 @@
expect_log "MethodParameters" "MethodParameters not preserved!"
}
+function test_nestmates_attribute() {
+ # Check that Java 11 NestMates attributes are preserved
+ $IJAR $NESTMATES_JAR $NESTMATES_IJAR || fail "ijar failed"
+ $JAVAP -classpath $NESTMATES_IJAR -v NestTest >& $TEST_log \
+ || fail "javap failed"
+ expect_log "NestMembers" "NestMembers not preserved!"
+}
+
function test_source_debug_extension_attribute() {
# Check that SourceDebugExtension attributes are dropped without a warning
$IJAR $SOURCEDEBUGEXT_JAR $SOURCEDEBUGEXT_IJAR >& $TEST_log || fail "ijar failed"
diff --git a/third_party/ijar/test/nestmates/NestTest.java b/third_party/ijar/test/nestmates/NestTest.java
new file mode 100644
index 0000000..5fc4362
--- /dev/null
+++ b/third_party/ijar/test/nestmates/NestTest.java
@@ -0,0 +1,24 @@
+// Copyright 2018 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/** A class that results in nestmate attributes in Java 11. */
+public class NestTest {
+ private static class P {
+ public void f() {}
+ }
+
+ public static void main(String[] args) {
+ new P().f();
+ }
+}
diff --git a/third_party/ijar/test/nestmates/nestmates.jar b/third_party/ijar/test/nestmates/nestmates.jar
new file mode 100644
index 0000000..1615e68
--- /dev/null
+++ b/third_party/ijar/test/nestmates/nestmates.jar
Binary files differ