Skip to content

Commit

Permalink
Make class file version more efficient and avoid experimental API on it.
Browse files Browse the repository at this point in the history
  • Loading branch information
raphw committed Sep 26, 2024
1 parent 1e38dd0 commit b7b3b65
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 149 deletions.
179 changes: 45 additions & 134 deletions byte-buddy-dep/src/main/java/net/bytebuddy/ClassFileVersion.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import net.bytebuddy.build.HashCodeAndEqualsPlugin;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.ClassFileLocator;
import net.bytebuddy.utility.OpenedClassReader;
import net.bytebuddy.utility.nullability.MaybeNull;
import org.objectweb.asm.Opcodes;

Expand Down Expand Up @@ -160,6 +159,33 @@ public class ClassFileVersion implements Comparable<ClassFileVersion>, Serializa
*/
public static final ClassFileVersion JAVA_V23 = new ClassFileVersion(Opcodes.V23);

/**
* An array of class file versions in their sorting order.
*/
private static final ClassFileVersion[] CLASS_FILE_VERSIONS = new ClassFileVersion[] {ClassFileVersion.JAVA_V1,
ClassFileVersion.JAVA_V2,
ClassFileVersion.JAVA_V3,
ClassFileVersion.JAVA_V4,
ClassFileVersion.JAVA_V5,
ClassFileVersion.JAVA_V6,
ClassFileVersion.JAVA_V7,
ClassFileVersion.JAVA_V8,
ClassFileVersion.JAVA_V9,
ClassFileVersion.JAVA_V10,
ClassFileVersion.JAVA_V11,
ClassFileVersion.JAVA_V12,
ClassFileVersion.JAVA_V13,
ClassFileVersion.JAVA_V14,
ClassFileVersion.JAVA_V15,
ClassFileVersion.JAVA_V16,
ClassFileVersion.JAVA_V17,
ClassFileVersion.JAVA_V18,
ClassFileVersion.JAVA_V19,
ClassFileVersion.JAVA_V20,
ClassFileVersion.JAVA_V21,
ClassFileVersion.JAVA_V22,
ClassFileVersion.JAVA_V23};

/**
* A version locator for the executing JVM.
*/
Expand Down Expand Up @@ -212,76 +238,20 @@ public static ClassFileVersion ofMinorMajor(int versionNumber) {
* @return The appropriate class file version.
*/
public static ClassFileVersion ofJavaVersionString(String javaVersionString) {
return ofJavaVersionString(javaVersionString, OpenedClassReader.EXPERIMENTAL);
}

/**
* Returns the Java class file by its representation by a version string in accordance to the formats known to <i>javac</i>.
*
* @param javaVersionString The Java version string.
* @param experimental {@code true} if unknown version strings should be parsed as if they were known.
* @return The appropriate class file version.
*/
public static ClassFileVersion ofJavaVersionString(String javaVersionString, boolean experimental) {
if (javaVersionString.equals("1.1")) {
return JAVA_V1;
} else if (javaVersionString.equals("1.2")) {
return JAVA_V2;
} else if (javaVersionString.equals("1.3")) {
return JAVA_V3;
} else if (javaVersionString.equals("1.4")) {
return JAVA_V4;
} else if (javaVersionString.equals("1.5") || javaVersionString.equals("5")) {
return JAVA_V5;
} else if (javaVersionString.equals("1.6") || javaVersionString.equals("6")) {
return JAVA_V6;
} else if (javaVersionString.equals("1.7") || javaVersionString.equals("7")) {
return JAVA_V7;
} else if (javaVersionString.equals("1.8") || javaVersionString.equals("8")) {
return JAVA_V8;
} else if (javaVersionString.equals("1.9") || javaVersionString.equals("9")) {
return JAVA_V9;
} else if (javaVersionString.equals("1.10") || javaVersionString.equals("10")) {
return JAVA_V10;
} else if (javaVersionString.equals("1.11") || javaVersionString.equals("11")) {
return JAVA_V11;
} else if (javaVersionString.equals("1.12") || javaVersionString.equals("12")) {
return JAVA_V12;
} else if (javaVersionString.equals("1.13") || javaVersionString.equals("13")) {
return JAVA_V13;
} else if (javaVersionString.equals("1.14") || javaVersionString.equals("14")) {
return JAVA_V14;
} else if (javaVersionString.equals("1.15") || javaVersionString.equals("15")) {
return JAVA_V15;
} else if (javaVersionString.equals("1.16") || javaVersionString.equals("16")) {
return JAVA_V16;
} else if (javaVersionString.equals("1.17") || javaVersionString.equals("17")) {
return JAVA_V17;
} else if (javaVersionString.equals("1.18") || javaVersionString.equals("18")) {
return JAVA_V18;
} else if (javaVersionString.equals("1.19") || javaVersionString.equals("19")) {
return JAVA_V19;
} else if (javaVersionString.equals("1.20") || javaVersionString.equals("20")) {
return JAVA_V20;
} else if (javaVersionString.equals("1.21") || javaVersionString.equals("21")) {
return JAVA_V21;
} else if (javaVersionString.equals("1.22") || javaVersionString.equals("22")) {
return JAVA_V22;
} else if (javaVersionString.equals("1.23") || javaVersionString.equals("23")) {
return JAVA_V23;
} else {
if (experimental) {
try {
int version = Integer.parseInt(javaVersionString.startsWith("1.")
? javaVersionString.substring(2)
: javaVersionString);
if (version > 0) {
return new ClassFileVersion(BASE_VERSION + version);
}
} catch (NumberFormatException ignored) {
int index = javaVersionString.indexOf('.');
try {
int javaVersion;
if (index == -1) {
javaVersion = Integer.parseInt(javaVersionString);
} else {
javaVersion = Integer.parseInt(javaVersionString.substring(index + 1));
if (Integer.parseInt(javaVersionString.substring(0, index)) != 1 || javaVersion > 8) {
throw new IllegalArgumentException("Java versions with minor version must be of format 1.[1-7]: " + javaVersionString);
}
}
throw new IllegalArgumentException("Unknown Java version string: " + javaVersionString);
return ofJavaVersion(javaVersion);
} catch (NumberFormatException exception) {
throw new IllegalStateException("Failed to read Java version from: " + javaVersionString, exception);
}
}

Expand All @@ -293,71 +263,12 @@ public static ClassFileVersion ofJavaVersionString(String javaVersionString, boo
* @return A wrapper for the given Java class file version.
*/
public static ClassFileVersion ofJavaVersion(int javaVersion) {
return ofJavaVersion(javaVersion, OpenedClassReader.EXPERIMENTAL);
}

/**
* Creates a class file version for a given major release of Java. Currently, all versions reaching from
* Java 1 to Java 9 are supported.
*
* @param javaVersion The Java version.
* @param experimental {@code true} if unknown Java versions should also be considered.
* @return A wrapper for the given Java class file version.
*/
public static ClassFileVersion ofJavaVersion(int javaVersion, boolean experimental) {
switch (javaVersion) {
case 1:
return JAVA_V1;
case 2:
return JAVA_V2;
case 3:
return JAVA_V3;
case 4:
return JAVA_V4;
case 5:
return JAVA_V5;
case 6:
return JAVA_V6;
case 7:
return JAVA_V7;
case 8:
return JAVA_V8;
case 9:
return JAVA_V9;
case 10:
return JAVA_V10;
case 11:
return JAVA_V11;
case 12:
return JAVA_V12;
case 13:
return JAVA_V13;
case 14:
return JAVA_V14;
case 15:
return JAVA_V15;
case 16:
return JAVA_V16;
case 17:
return JAVA_V17;
case 18:
return JAVA_V18;
case 19:
return JAVA_V19;
case 20:
return JAVA_V20;
case 21:
return JAVA_V21;
case 22:
return JAVA_V22;
case 23:
return JAVA_V23;
default:
if (experimental && javaVersion > 0) {
return new ClassFileVersion(BASE_VERSION + javaVersion);
} else {
throw new IllegalArgumentException("Unknown Java version: " + javaVersion);
}
if (javaVersion < 1) {
throw new IllegalArgumentException("Java version must be positive: " + javaVersion);
} else if (javaVersion - 1 < CLASS_FILE_VERSIONS.length) {
return CLASS_FILE_VERSIONS[javaVersion - 1];
} else {
return new ClassFileVersion(BASE_VERSION + javaVersion);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,16 @@ public void testLatestVersion() throws Exception {
assertThat(ClassFileVersion.latest().getMajorVersion(), is((short) value));
}

@Test(expected = IllegalArgumentException.class)
public void testNegativeVersion() throws Exception {
ClassFileVersion.ofJavaVersion(0);
}

@Test(expected = IllegalArgumentException.class)
public void testOneDotTooNew() throws Exception {
ClassFileVersion.ofJavaVersionString("1.9");
}

@Test(expected = IllegalArgumentException.class)
public void testIllegalClassFile() throws Exception {
ClassFileVersion.ofClassFile(new byte[0]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,21 +66,21 @@ public static Collection<Object[]> data() {
{6, 6, Arrays.asList("1.6", "6"), Opcodes.V1_6, (short) 50, (short) 0, true, false, false},
{7, 7, Arrays.asList("1.7", "7"), Opcodes.V1_7, (short) 51, (short) 0, true, true, false},
{8, 8, Arrays.asList("1.8", "8"), Opcodes.V1_8, (short) 52, (short) 0, true, true, true},
{9, 9, Arrays.asList("1.9", "9"), Opcodes.V9, (short) 53, (short) 0, true, true, true},
{10, 10, Arrays.asList("1.10", "10"), Opcodes.V10, (short) 54, (short) 0, true, true, true},
{11, 11, Arrays.asList("1.11", "11"), Opcodes.V11, (short) 55, (short) 0, true, true, true},
{12, 12, Arrays.asList("1.12", "12"), Opcodes.V12, (short) 56, (short) 0, true, true, true},
{13, 13, Arrays.asList("1.13", "13"), Opcodes.V13, (short) 57, (short) 0, true, true, true},
{14, 14, Arrays.asList("1.14", "14"), Opcodes.V14, (short) 58, (short) 0, true, true, true},
{15, 15, Arrays.asList("1.15", "15"), Opcodes.V15, (short) 59, (short) 0, true, true, true},
{16, 16, Arrays.asList("1.16", "16"), Opcodes.V16, (short) 60, (short) 0, true, true, true},
{17, 17, Arrays.asList("1.17", "17"), Opcodes.V17, (short) 61, (short) 0, true, true, true},
{18, 18, Arrays.asList("1.18", "18"), Opcodes.V18, (short) 62, (short) 0, true, true, true},
{19, 19, Arrays.asList("1.19", "19"), Opcodes.V19, (short) 63, (short) 0, true, true, true},
{20, 20, Arrays.asList("1.20", "20"), Opcodes.V20, (short) 64, (short) 0, true, true, true},
{21, 21, Arrays.asList("1.21", "21"), Opcodes.V21, (short) 65, (short) 0, true, true, true},
{22, 22, Arrays.asList("1.22", "22"), Opcodes.V22, (short) 66, (short) 0, true, true, true},
{23, 23, Arrays.asList("1.23", "23"), Opcodes.V23, (short) 67, (short) 0, true, true, true}
{9, 9, Collections.singletonList("9"), Opcodes.V9, (short) 53, (short) 0, true, true, true},
{10, 10, Collections.singletonList("10"), Opcodes.V10, (short) 54, (short) 0, true, true, true},
{11, 11, Collections.singletonList("11"), Opcodes.V11, (short) 55, (short) 0, true, true, true},
{12, 12, Collections.singletonList("12"), Opcodes.V12, (short) 56, (short) 0, true, true, true},
{13, 13, Collections.singletonList("13"), Opcodes.V13, (short) 57, (short) 0, true, true, true},
{14, 14, Collections.singletonList("14"), Opcodes.V14, (short) 58, (short) 0, true, true, true},
{15, 15, Collections.singletonList("15"), Opcodes.V15, (short) 59, (short) 0, true, true, true},
{16, 16, Collections.singletonList("16"), Opcodes.V16, (short) 60, (short) 0, true, true, true},
{17, 17, Collections.singletonList("17"), Opcodes.V17, (short) 61, (short) 0, true, true, true},
{18, 18, Collections.singletonList("18"), Opcodes.V18, (short) 62, (short) 0, true, true, true},
{19, 19, Collections.singletonList("19"), Opcodes.V19, (short) 63, (short) 0, true, true, true},
{20, 20, Collections.singletonList("20"), Opcodes.V20, (short) 64, (short) 0, true, true, true},
{21, 21, Collections.singletonList("21"), Opcodes.V21, (short) 65, (short) 0, true, true, true},
{22, 22, Collections.singletonList("22"), Opcodes.V22, (short) 66, (short) 0, true, true, true},
{23, 23, Collections.singletonList("23"), Opcodes.V23, (short) 67, (short) 0, true, true, true}
});
}

Expand Down

0 comments on commit b7b3b65

Please sign in to comment.