blob: 3e89a4f466de68671c1f2ef9ea9f5cb45169b2b8 [file] [log] [blame]
// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.desugar.desugaredlibrary;
import static com.android.tools.r8.utils.codeinspector.CodeMatchers.invokesMethod;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static com.android.tools.r8.utils.codeinspector.Matchers.onlyIf;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.StringResource;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ir.desugar.DesugaredLibraryConfiguration;
import com.android.tools.r8.ir.desugar.DesugaredLibraryConfigurationParser;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.android.tools.r8.utils.structural.Ordered;
import com.google.common.collect.ImmutableList;
import java.nio.file.Path;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.function.Supplier;
import org.hamcrest.Matcher;
import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
@RunWith(Parameterized.class)
public class ObjectsTest extends DesugaredLibraryTestBase implements Opcodes {
private final TestParameters parameters;
private final boolean libraryDesugarJavaUtilObjects;
private final boolean shrinkDesugaredLibrary = false;
private final Path androidJar;
@Parameters(name = "{0}, libraryDesugarJavaUtilObjects: {1}")
public static List<Object[]> data() {
return buildParameters(
getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build(),
BooleanUtils.values());
}
public ObjectsTest(TestParameters parameters, boolean libraryDesugarJavaUtilObjects) {
this.parameters = parameters;
this.libraryDesugarJavaUtilObjects = libraryDesugarJavaUtilObjects;
// Using desugared library require a compile SDK of 26 or higher.
this.androidJar =
ToolHelper.getAndroidJar(Ordered.max(parameters.getApiLevel(), AndroidApiLevel.O));
}
DesugaredLibraryConfiguration desugaredLibraryConfiguration(
InternalOptions options, boolean libraryCompilation, TestParameters parameters) {
return new DesugaredLibraryConfigurationParser(
options.dexItemFactory(),
options.reporter,
libraryCompilation,
parameters.getApiLevel().getLevel())
.parse(
StringResource.fromFile(
libraryDesugarJavaUtilObjects
? ToolHelper.getDesugarLibJsonForTestingAlternative3()
: ToolHelper.getDesugarLibJsonForTesting()));
}
private void configurationForProgramCompilation(InternalOptions options) {
options.desugaredLibraryConfiguration =
desugaredLibraryConfiguration(options, false, parameters);
}
private void configurationForLibraryCompilation(InternalOptions options) {
options.desugaredLibraryConfiguration =
desugaredLibraryConfiguration(options, true, parameters);
}
private Matcher<MethodSubject> invokesObjectsCompare(String holder) {
return invokesMethod(
"int",
holder,
"compare",
ImmutableList.of("java.lang.Object", "java.lang.Object", "java.util.Comparator"));
}
private Matcher<MethodSubject> invokesObjectsEquals(String holder) {
return invokesMethod(
"boolean", holder, "equals", ImmutableList.of("java.lang.Object", "java.lang.Object"));
}
private Matcher<MethodSubject> invokesObjectsDeepEquals(String holder) {
return invokesMethod(
"boolean", holder, "deepEquals", ImmutableList.of("java.lang.Object", "java.lang.Object"));
}
private Matcher<MethodSubject> invokesObjectsHash(String holder) {
return invokesMethod("int", holder, "hash", ImmutableList.of("java.lang.Object[]"));
}
private Matcher<MethodSubject> invokesObjectsHashCode(String holder) {
return invokesMethod("int", holder, "hashCode", ImmutableList.of("java.lang.Object"));
}
private Matcher<MethodSubject> invokesClassGetClass() {
return invokesMethod("java.lang.Class", "java.lang.Object", "getClass", ImmutableList.of());
}
private Matcher<MethodSubject> invokesObjectsRequireNonNull(String holder) {
return invokesMethod(
"java.lang.Object", holder, "requireNonNull", ImmutableList.of("java.lang.Object"));
}
private Matcher<MethodSubject> invokesObjectsRequireNonNullWithMessage(String holder) {
return invokesMethod(
"java.lang.Object",
holder,
"requireNonNull",
ImmutableList.of("java.lang.Object", "java.lang.String"));
}
private Matcher<MethodSubject> invokesObjectsRequireNonNullWithSupplier(
String holder, String Supplier) {
return invokesMethod(
"java.lang.Object",
holder,
"requireNonNull",
ImmutableList.of("java.lang.Object", Supplier));
}
private Matcher<MethodSubject> invokesObjectsToString(String holder) {
return invokesMethod(
"java.lang.String", holder, "toString", ImmutableList.of("java.lang.Object"));
}
private Matcher<MethodSubject> invokesObjectsToStringWithNullDefault(String holder) {
return invokesMethod(
"java.lang.String",
holder,
"toString",
ImmutableList.of("java.lang.Object", "java.lang.String"));
}
private Matcher<MethodSubject> invokesObjectsIsNull(String holder) {
return invokesMethod("boolean", holder, "isNull", ImmutableList.of("java.lang.Object"));
}
private Matcher<MethodSubject> invokesObjectsNonNull(String holder) {
return invokesMethod("boolean", holder, "nonNull", ImmutableList.of("java.lang.Object"));
}
private void inspect(CodeInspector inspector) {
ClassSubject testClass = inspector.clazz(TestClass.class);
assertThat(testClass, isPresent());
// Objects.equals as added in Android K, so when backporting, this is only backported below K.
// However, for library desugaring, the desugaring of Objects.equals happens all the way up to
// Android M, as that is grouped with other methods like Objects.requireNonNull which was
// added in Android N.
boolean invokeJavaUtilObjects =
!libraryDesugarJavaUtilObjects
&& parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.K)
|| (libraryDesugarJavaUtilObjects
&& parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.N));
boolean invokeJDollarUtilObjects =
libraryDesugarJavaUtilObjects && parameters.getApiLevel().isLessThan(AndroidApiLevel.N);
boolean invokeJavaUtilObjectsWithSupplier =
!libraryDesugarJavaUtilObjects || !parameters.getApiLevel().isLessThan(AndroidApiLevel.N);
boolean invokeJDollarUtilObjectsWithSupplier =
libraryDesugarJavaUtilObjects && parameters.getApiLevel().isLessThan(AndroidApiLevel.N);
assertThat(
testClass.uniqueMethodWithName("objectsCompare"),
onlyIf(invokeJavaUtilObjects, invokesObjectsCompare("java.util.Objects")));
assertThat(
testClass.uniqueMethodWithName("objectsCompare"),
onlyIf(invokeJDollarUtilObjects, invokesObjectsCompare("j$.util.Objects")));
assertThat(
testClass.uniqueMethodWithName("objectsDeepEquals"),
onlyIf(invokeJavaUtilObjects, invokesObjectsDeepEquals("java.util.Objects")));
assertThat(
testClass.uniqueMethodWithName("objectsDeepEquals"),
onlyIf(invokeJDollarUtilObjects, invokesObjectsDeepEquals("j$.util.Objects")));
assertThat(
testClass.uniqueMethodWithName("objectsEquals"),
onlyIf(invokeJavaUtilObjects, invokesObjectsEquals("java.util.Objects")));
assertThat(
testClass.uniqueMethodWithName("objectsEquals"),
onlyIf(invokeJDollarUtilObjects, invokesObjectsEquals("j$.util.Objects")));
assertThat(
testClass.uniqueMethodWithName("objectsHash"),
onlyIf(invokeJavaUtilObjects, invokesObjectsHash("java.util.Objects")));
assertThat(
testClass.uniqueMethodWithName("objectsHash"),
onlyIf(invokeJDollarUtilObjects, invokesObjectsHash("j$.util.Objects")));
assertThat(
testClass.uniqueMethodWithName("objectsHashCode"),
onlyIf(invokeJavaUtilObjects, invokesObjectsHashCode("java.util.Objects")));
assertThat(
testClass.uniqueMethodWithName("objectsHashCode"),
onlyIf(invokeJDollarUtilObjects, invokesObjectsHashCode("j$.util.Objects")));
assertThat(
testClass.uniqueMethodWithName("objectsRequireNonNull"),
onlyIf(invokeJavaUtilObjects, invokesObjectsRequireNonNull("java.util.Objects")));
assertThat(
testClass.uniqueMethodWithName("objectsRequireNonNull"),
onlyIf(parameters.getApiLevel().isLessThan(AndroidApiLevel.K), invokesClassGetClass()));
assertThat(
testClass.uniqueMethodWithName("objectsRequireNonNullWithMessage"),
onlyIf(
invokeJavaUtilObjects, invokesObjectsRequireNonNullWithMessage("java.util.Objects")));
assertThat(
testClass.uniqueMethodWithName("objectsRequireNonNullWithMessage"),
onlyIf(
invokeJDollarUtilObjects, invokesObjectsRequireNonNullWithMessage("j$.util.Objects")));
assertThat(
testClass.uniqueMethodWithName("objectsRequireNonNullWithSupplier"),
onlyIf(
invokeJavaUtilObjectsWithSupplier,
invokesObjectsRequireNonNullWithSupplier(
"java.util.Objects", "java.util.function.Supplier")));
assertThat(
testClass.uniqueMethodWithName("objectsRequireNonNullWithSupplier"),
onlyIf(
invokeJDollarUtilObjectsWithSupplier,
invokesObjectsRequireNonNullWithSupplier(
"j$.util.Objects", "j$.util.function.Supplier")));
assertThat(
testClass.uniqueMethodWithName("objectsToString"),
onlyIf(invokeJavaUtilObjects, invokesObjectsToString("java.util.Objects")));
assertThat(
testClass.uniqueMethodWithName("objectsToString"),
onlyIf(invokeJDollarUtilObjects, invokesObjectsToString("j$.util.Objects")));
assertThat(
testClass.uniqueMethodWithName("objectsToStringWithNullDefault"),
onlyIf(invokeJavaUtilObjects, invokesObjectsToStringWithNullDefault("java.util.Objects")));
assertThat(
testClass.uniqueMethodWithName("objectsToStringWithNullDefault"),
onlyIf(invokeJDollarUtilObjects, invokesObjectsToStringWithNullDefault("j$.util.Objects")));
invokeJavaUtilObjects = parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.N);
assertThat(
testClass.uniqueMethodWithName("objectsIsNull"),
onlyIf(invokeJavaUtilObjects, invokesObjectsIsNull("java.util.Objects")));
assertThat(
testClass.uniqueMethodWithName("objectsIsNull"),
onlyIf(invokeJDollarUtilObjects, invokesObjectsIsNull("j$.util.Objects")));
assertThat(
testClass.uniqueMethodWithName("objectsNonNull"),
onlyIf(invokeJavaUtilObjects, invokesObjectsNonNull("java.util.Objects")));
assertThat(
testClass.uniqueMethodWithName("objectsNonNull"),
onlyIf(invokeJDollarUtilObjects, invokesObjectsNonNull("j$.util.Objects")));
}
@Test
public void testD8Cf() throws Exception {
// Adjust API level if running on JDK 8. The java.util.Objects methods added in
// Android R where added in JDK 9, so setting the the API level to Android P will backport
// these methods for JDK 8.
AndroidApiLevel apiLevel = parameters.getApiLevel();
if (parameters.getRuntime().isCf()
&& parameters.getRuntime().asCf().getVm() == CfVm.JDK8
&& apiLevel.isGreaterThanOrEqualTo(AndroidApiLevel.R)) {
apiLevel = AndroidApiLevel.P;
}
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
// Use D8 to desugar with Java classfile output.
Path jar =
testForD8(Backend.CF)
.addLibraryFiles(androidJar)
.addOptionsModification(this::configurationForProgramCompilation)
.addInnerClasses(ObjectsTest.class)
.addProgramClassFileData(dumpAndroidRUtilsObjectsMethods())
.setMinApi(apiLevel)
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
.compile()
.inspect(this::inspect)
.writeToZip();
if (parameters.getRuntime().isDex()) {
// Collection keep rules is only implemented in the DEX writer.
String desugaredLibraryKeepRules = keepRuleConsumer.get();
if (desugaredLibraryKeepRules != null) {
assertEquals(0, desugaredLibraryKeepRules.length());
desugaredLibraryKeepRules = "-keep class * { *; }";
}
// Convert to DEX without desugaring and run.
testForD8()
.addLibraryFiles(androidJar)
.addProgramFiles(jar)
.setMinApi(apiLevel)
.disableDesugaring()
.compile()
.addDesugaredCoreLibraryRunClassPath(
(apiLevel_, keepRules, shrink) ->
buildDesugaredLibrary(
apiLevel_,
keepRules,
shrink,
ImmutableList.of(),
this::configurationForLibraryCompilation),
parameters.getApiLevel(),
desugaredLibraryKeepRules,
shrinkDesugaredLibrary)
.run(
parameters.getRuntime(),
TestClass.class,
Boolean.toString(libraryDesugarJavaUtilObjects))
.assertSuccessWithOutput(expectedOutput(libraryDesugarJavaUtilObjects));
} else {
// Build the desugared library in class file format.
Path desugaredLib =
getDesugaredLibraryInCF(parameters, this::configurationForLibraryCompilation);
// Run on the JVM with desuagred library on classpath.
testForJvm()
.addProgramFiles(jar)
.addRunClasspathFiles(desugaredLib)
.run(
parameters.getRuntime(),
TestClass.class,
Boolean.toString(libraryDesugarJavaUtilObjects))
.assertSuccessWithOutput(expectedOutput(libraryDesugarJavaUtilObjects));
}
}
@Test
public void testD8() throws Exception {
Assume.assumeTrue(parameters.getRuntime().isDex());
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
.addLibraryFiles(androidJar)
.addOptionsModification(this::configurationForProgramCompilation)
.addInnerClasses(ObjectsTest.class)
.addProgramClassFileData(dumpAndroidRUtilsObjectsMethods())
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
.compile()
.addDesugaredCoreLibraryRunClassPath(
(apiLevel, keepRules, shrink) ->
buildDesugaredLibrary(
apiLevel,
keepRules,
shrink,
ImmutableList.of(),
this::configurationForLibraryCompilation),
parameters.getApiLevel(),
keepRuleConsumer.get(),
shrinkDesugaredLibrary)
.inspect(this::inspect)
.run(
parameters.getRuntime(),
TestClass.class,
Boolean.toString(libraryDesugarJavaUtilObjects))
.assertSuccessWithOutput(expectedOutput(libraryDesugarJavaUtilObjects));
}
@Test
public void testR8() throws Exception {
Assume.assumeTrue(parameters.getRuntime().isDex());
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(parameters.getBackend())
.addLibraryFiles(androidJar)
.addOptionsModification(this::configurationForProgramCompilation)
.addInnerClasses(ObjectsTest.class)
.addKeepMainRule(TestClass.class)
.addProgramClassFileData(dumpAndroidRUtilsObjectsMethods())
.enableInliningAnnotations()
.noMinification()
.addKeepRules("-keep class AndroidRUtilsObjectsMethods { *; }")
.addKeepRules("-neverinline class AndroidRUtilsObjectsMethods { *; }")
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
.compile()
.addDesugaredCoreLibraryRunClassPath(
(apiLevel, keepRules, shrink) ->
buildDesugaredLibrary(
apiLevel,
keepRules,
shrink,
ImmutableList.of(),
this::configurationForLibraryCompilation),
parameters.getApiLevel(),
keepRuleConsumer.get(),
shrinkDesugaredLibrary)
.inspect(this::inspect)
.run(
parameters.getRuntime(),
TestClass.class,
Boolean.toString(libraryDesugarJavaUtilObjects))
.assertSuccessWithOutput(expectedOutput(libraryDesugarJavaUtilObjects));
}
private String expectedOutput(boolean objectsRequireNonNullWithSupplierSupported) {
return StringUtils.lines(
"1",
"false",
"false",
Objects.toString(Objects.hash(1, 2)),
"4",
"NPE",
"Was null",
objectsRequireNonNullWithSupplierSupported
? "Supplier said was null"
: "Not supported (b/174840626)",
"5",
"6",
"true",
"false",
"1",
"2",
"3",
"4");
}
static class TestClass {
@NeverInline
private static void objectsCompare(String s1, String s2) {
Comparator<String> stringsNullLast =
(o1, o2) -> {
if (o1 == null) {
return o2 == null ? 0 : 1;
}
return o2 == null ? -1 : o1.compareTo(o2);
};
System.out.println(Objects.compare(s1, s2, stringsNullLast));
}
@NeverInline
private static void objectsDeepEquals(Object o1, Object o2) {
System.out.println(Objects.deepEquals(o1, o2));
}
@NeverInline
private static void objectsEquals(Object o1, Object o2) {
System.out.println(Objects.equals(o1, o2));
}
@NeverInline
private static void objectsHash(Object o1, Object o2) {
System.out.println(Objects.hash(o1, o2));
}
@NeverInline
private static void objectsHashCode(Object o) {
System.out.println(Objects.hashCode(o));
}
@NeverInline
private static void objectsRequireNonNull(Object o) {
try {
System.out.println(Objects.requireNonNull(o));
} catch (NullPointerException e) {
System.out.println("NPE");
}
}
@NeverInline
private static void objectsRequireNonNullWithMessage(Object o, String message) {
try {
System.out.println(Objects.requireNonNull(o, message));
} catch (NullPointerException e) {
System.out.println(e.getMessage());
}
}
@NeverInline
private static void objectsRequireNonNullWithSupplier(
Object o, Supplier<String> messageSupplier) {
try {
System.out.println(Objects.requireNonNull(o, messageSupplier));
} catch (NullPointerException e) {
System.out.println(e.getMessage());
}
}
@NeverInline
private static void objectsToString(Object o) {
System.out.println(Objects.toString(o));
}
@NeverInline
private static void objectsToStringWithNullDefault(Object o, String nullDefault) {
System.out.println(Objects.toString(o, nullDefault));
}
@NeverInline
private static void objectsIsNull(Object o) {
System.out.println(Objects.isNull(o));
}
@NeverInline
private static void objectsNonNull(Object o) {
System.out.println(Objects.nonNull(o));
}
public static void main(String[] args) throws Exception {
boolean objectsRequireNonNullWithSupplierSupported = Boolean.parseBoolean(args[0]);
// Android K methods.
objectsCompare("b", "a");
objectsDeepEquals(args, new Object());
objectsEquals(makeNullable(args), new Object());
objectsHash(1, 2);
objectsHashCode(4);
objectsRequireNonNull(getNonNullableNull());
objectsRequireNonNullWithMessage(null, "Was null");
if (objectsRequireNonNullWithSupplierSupported) {
objectsRequireNonNullWithSupplier(null, () -> "Supplier said was null");
} else {
System.out.println("Not supported (b/174840626)");
}
objectsToString(makeNullable("5"));
objectsToStringWithNullDefault(getNonNullableNull(), "6");
// Android N methods.
objectsIsNull(getNonNullableNull());
objectsNonNull(getNonNullableNull());
// Android R methods.
Class<?> c = Class.forName("AndroidRUtilsObjectsMethods");
c.getDeclaredMethod("checkFromIndexSize", int.class, int.class, int.class)
.invoke(null, 1, 2, 10);
c.getDeclaredMethod("checkFromToIndex", int.class, int.class, int.class)
.invoke(null, 2, 4, 10);
c.getDeclaredMethod("checkIndex", int.class, int.class).invoke(null, 3, 10);
c.getDeclaredMethod("requireNonNullElse", Object.class, Object.class).invoke(null, null, 4);
// TODO(b/174840626) Also support requireNonNullElseGet.
}
private static Object makeNullable(Object obj) {
return System.currentTimeMillis() > 0 ? obj : null;
}
private static Object getNonNullableNull() {
return System.currentTimeMillis() > 0 ? null : new Object();
}
}
/*
Dump below is from this source:
import java.util.function.Supplier;
import java.util.Objects;
public class AndroidRUtilsObjectsMethods {
public static void checkFromIndexSize(int fromIndex, int size, int length) {
System.out.println(Objects.checkFromIndexSize(fromIndex, size, length));
}
public static void checkFromToIndex(int fromIndex, int toIndex, int length) {
System.out.println(Objects.checkFromToIndex(fromIndex, toIndex, length));
}
public static void checkIndex(int index, int length) {
System.out.println(Objects.checkIndex(index, length));
}
public static <T> void requireNonNullElse(T obj, T defaultObj) {
System.out.println(Objects.requireNonNullElse(obj, defaultObj));
}
public static <T> void requireNonNullElseGet(T obj, Supplier<? extends T> supplier) {
System.out.println(Objects.requireNonNullElse(obj, supplier));
}
}
This is added as a dump as it use APIs which are only abailable from JDK 9.
*/
public static byte[] dumpAndroidRUtilsObjectsMethods() throws Exception {
ClassWriter classWriter = new ClassWriter(0);
MethodVisitor methodVisitor;
classWriter.visit(
V9, ACC_PUBLIC | ACC_SUPER, "AndroidRUtilsObjectsMethods", null, "java/lang/Object", null);
classWriter.visitSource("AndroidRUtilsObjectsMethods.java", null);
{
methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
methodVisitor.visitCode();
Label label0 = new Label();
methodVisitor.visitLabel(label0);
methodVisitor.visitLineNumber(3, label0);
methodVisitor.visitVarInsn(ALOAD, 0);
methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(1, 1);
methodVisitor.visitEnd();
}
{
methodVisitor =
classWriter.visitMethod(
ACC_PUBLIC | ACC_STATIC, "checkFromIndexSize", "(III)V", null, null);
methodVisitor.visitCode();
Label label0 = new Label();
methodVisitor.visitLabel(label0);
methodVisitor.visitLineNumber(5, label0);
methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
methodVisitor.visitVarInsn(ILOAD, 0);
methodVisitor.visitVarInsn(ILOAD, 1);
methodVisitor.visitVarInsn(ILOAD, 2);
methodVisitor.visitMethodInsn(
INVOKESTATIC, "java/util/Objects", "checkFromIndexSize", "(III)I", false);
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(I)V", false);
Label label1 = new Label();
methodVisitor.visitLabel(label1);
methodVisitor.visitLineNumber(6, label1);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(4, 3);
methodVisitor.visitEnd();
}
{
methodVisitor =
classWriter.visitMethod(
ACC_PUBLIC | ACC_STATIC, "checkFromToIndex", "(III)V", null, null);
methodVisitor.visitCode();
Label label0 = new Label();
methodVisitor.visitLabel(label0);
methodVisitor.visitLineNumber(8, label0);
methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
methodVisitor.visitVarInsn(ILOAD, 0);
methodVisitor.visitVarInsn(ILOAD, 1);
methodVisitor.visitVarInsn(ILOAD, 2);
methodVisitor.visitMethodInsn(
INVOKESTATIC, "java/util/Objects", "checkFromToIndex", "(III)I", false);
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(I)V", false);
Label label1 = new Label();
methodVisitor.visitLabel(label1);
methodVisitor.visitLineNumber(9, label1);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(4, 3);
methodVisitor.visitEnd();
}
{
methodVisitor =
classWriter.visitMethod(ACC_PUBLIC | ACC_STATIC, "checkIndex", "(II)V", null, null);
methodVisitor.visitCode();
Label label0 = new Label();
methodVisitor.visitLabel(label0);
methodVisitor.visitLineNumber(11, label0);
methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
methodVisitor.visitVarInsn(ILOAD, 0);
methodVisitor.visitVarInsn(ILOAD, 1);
methodVisitor.visitMethodInsn(
INVOKESTATIC, "java/util/Objects", "checkIndex", "(II)I", false);
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(I)V", false);
Label label1 = new Label();
methodVisitor.visitLabel(label1);
methodVisitor.visitLineNumber(12, label1);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(3, 2);
methodVisitor.visitEnd();
}
{
methodVisitor =
classWriter.visitMethod(
ACC_PUBLIC | ACC_STATIC,
"requireNonNullElse",
"(Ljava/lang/Object;Ljava/lang/Object;)V",
"<T:Ljava/lang/Object;>(TT;TT;)V",
null);
methodVisitor.visitCode();
Label label0 = new Label();
methodVisitor.visitLabel(label0);
methodVisitor.visitLineNumber(14, label0);
methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
methodVisitor.visitVarInsn(ALOAD, 0);
methodVisitor.visitVarInsn(ALOAD, 1);
methodVisitor.visitMethodInsn(
INVOKESTATIC,
"java/util/Objects",
"requireNonNullElse",
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
false);
methodVisitor.visitMethodInsn(
INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/Object;)V", false);
Label label1 = new Label();
methodVisitor.visitLabel(label1);
methodVisitor.visitLineNumber(15, label1);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(3, 2);
methodVisitor.visitEnd();
}
{
methodVisitor =
classWriter.visitMethod(
ACC_PUBLIC | ACC_STATIC,
"requireNonNullElseGet",
"(Ljava/lang/Object;Ljava/util/function/Supplier;)V",
"<T:Ljava/lang/Object;>(TT;Ljava/util/function/Supplier<+TT;>;)V",
null);
methodVisitor.visitCode();
Label label0 = new Label();
methodVisitor.visitLabel(label0);
methodVisitor.visitLineNumber(18, label0);
methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
methodVisitor.visitVarInsn(ALOAD, 0);
methodVisitor.visitVarInsn(ALOAD, 1);
methodVisitor.visitMethodInsn(
INVOKESTATIC,
"java/util/Objects",
"requireNonNullElse",
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
false);
methodVisitor.visitMethodInsn(
INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/Object;)V", false);
Label label1 = new Label();
methodVisitor.visitLabel(label1);
methodVisitor.visitLineNumber(19, label1);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(3, 2);
methodVisitor.visitEnd();
}
classWriter.visitEnd();
return classWriter.toByteArray();
}
}