Skip to content

Commit

Permalink
Merge branch 'main' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
wagyourtail committed Sep 13, 2024
2 parents 8be0158 + 2e43ca3 commit 747ca0a
Show file tree
Hide file tree
Showing 21 changed files with 416 additions and 114 deletions.
12 changes: 6 additions & 6 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- name: Set up JDK 7 (fails from toolchain)
uses: actions/setup-java@v4
Expand All @@ -31,25 +31,25 @@ jobs:
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }}
run: ./gradlew publish -Pmvn.user=${{ secrets.MAVEN_USER }} -Pmvn.key=${{ secrets.MAVEN_TOKEN }} -PossrhUsername=${{ secrets.OSSRH_USERNAME }} -PossrhPassword=${{ secrets.OSSRH_PASSWORD }} -Pgradle.publish.key=${{ secrets.GRADLE_PUBLISH_KEY }} -Pgradle.publish.secret=${{ secrets.GRADLE_PUBLISH_SECRET }}

- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v4
with:
name: base
path: build/libs

- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v4
with:
name: api
path: java-api/build/libs

- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v4
with:
name: gradle
path: gradle-plugin/build/libs

- name: Build Site
run: ./gradlew :site:build

- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v4
with:
name: site
path: site/build/libs
Expand All @@ -62,7 +62,7 @@ jobs:
properties: 'version'

- name: Upload to Release
uses: JasonEtco/upload-to-release@v0.1.1
uses: JasonEtco/upload-to-release@master
with:
args: ./build/libs/jvmdowngrader-${{ steps.gradle_properties.outputs.version }}-all.jar application/jar
env:
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/build_snapshot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- name: Set up JDK 7 (fails from toolchain)
uses: actions/setup-java@v4
Expand All @@ -33,17 +33,17 @@ jobs:
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }}
run: ./gradlew publish -Pversion_snapshot -Pmvn.user=${{ secrets.MAVEN_USER }} -Pmvn.key=${{ secrets.MAVEN_TOKEN }}

- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v4
with:
name: base
path: build/libs

- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v4
with:
name: api
path: java-api/build/libs

- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v4
with:
name: gradle
path: gradle-plugin/build/libs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ public static void main(String[] args) throws IOException, URISyntaxException {
var versions = new HashMap<Integer, List<Path>>();
try (var folders = Files.newDirectoryStream(fs.getPath("/"))) {
for (var folder : folders) {
folder.getFileName().toString().chars().map(c -> Character.digit(c, 36)).forEach(javaVersion -> versions.computeIfAbsent(javaVersion, k -> new ArrayList<>()).add(folder));
folder.getFileName().toString().chars().map(c -> Character.digit(c, 36))
.forEach(javaVersion -> versions.computeIfAbsent(javaVersion, k -> new ArrayList<>()).add(folder));
}
}

Expand Down Expand Up @@ -97,11 +98,12 @@ public static void main(String[] args) throws IOException, URISyntaxException {
}
System.out.println("Checking version " + stubVersion);

Map<Type, Type> stubClassTypes = versionProvider.classStubs.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().getFirst()));
Set<FullyQualifiedMemberNameAndDesc> stubClassMethods = versionProvider.classStubs.entrySet().stream().flatMap (e ->
Stream.concat(
Arrays.stream(e.getValue().getSecond().getFirst().getDeclaredMethods()),
Arrays.stream(e.getValue().getSecond().getFirst().getConstructors())
Map<Type, Type> stubClassTypes = versionProvider.classStubs.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().getFirst()));
Set<FullyQualifiedMemberNameAndDesc> stubClassMethods = versionProvider.classStubs.entrySet().stream()
.flatMap (e -> Stream.concat(
Arrays.stream(e.getValue().getSecond().getFirst().getDeclaredMethods()),
Arrays.stream(e.getValue().getSecond().getFirst().getConstructors())
).filter(m ->
(m.getModifiers() & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) != 0 &&
(m.getModifiers() & Opcodes.ACC_SYNTHETIC) == 0 &&
Expand All @@ -112,7 +114,9 @@ public static void main(String[] args) throws IOException, URISyntaxException {
).map(MemberNameAndDesc::fromMember)
.map(m -> m.toFullyQualified(e.getValue().getFirst()))
).collect(Collectors.toSet());
var unmatchedStubs = versionProvider.stubMappings.values().stream().flatMap(value -> Stream.of(value.getMethodStubMap().values().stream(), value.getMethodModifyMap().values().stream()).flatMap(e -> e)).map(Pair::getFirst).collect(Collectors.toList());
var unmatchedStubs = versionProvider.stubMappings.values().stream().flatMap(value ->
Stream.of(value.getMethodStubMap().values().stream(), value.getMethodModifyMap().values().stream())
.flatMap(e -> e)).map(Pair::getFirst).collect(Collectors.toList());

try {
var requiredStubs = new ArrayList<MemberInfo>();
Expand Down Expand Up @@ -222,31 +226,26 @@ public static void main(String[] args) throws IOException, URISyntaxException {
}

var total = availableStubCount + onlyOnParentStubCount + missingStubCount;
System.out.println("Version " + stubVersion + " has " + availableStubCount + " available stubs, " + onlyOnParentStubCount + " only on parent stubs, and " + missingStubCount + " missing stubs. Total: " + total);

if (!missingStubs.isEmpty()) {
var missing = Path.of("./coverage/" + stubVersion + "/missing.txt");
writeList(missingStubs, missing);
}

if (!parentOnlyStubs.isEmpty()) {
var parentOnly = Path.of("./coverage/" + stubVersion + "/parentOnly.txt");
writeList(parentOnlyStubs, parentOnly);
}
if (!unmatchedStubs.isEmpty() || !stubClassMethods.isEmpty()) {
var unmatched = Path.of("./coverage/" + stubVersion + "/unmatched.txt");
writeList(
Stream.concat(
unmatchedStubs.stream()
.filter(e -> !e.isAnnotationPresent(CoverageIgnore.class))
.map(FullyQualifiedMemberNameAndDesc::of),
stubClassMethods.stream()
).map(e -> new MemberInfo("unknown", e, false, false))
.collect(Collectors.toList()),
unmatched
);
}

System.out.println("Version " + stubVersion + " has " + availableStubCount + " available stubs, " +
onlyOnParentStubCount + " only on parent stubs, and " + missingStubCount + " missing stubs. Total: " + total);

var missing = Path.of("./coverage/" + stubVersion + "/missing.txt");
writeList(missingStubs, missing);

var parentOnly = Path.of("./coverage/" + stubVersion + "/parentOnly.txt");
writeList(parentOnlyStubs, parentOnly);

var unmatched = Path.of("./coverage/" + stubVersion + "/unmatched.txt");
writeList(
Stream.concat(
unmatchedStubs.stream()
.filter(e -> !e.isAnnotationPresent(CoverageIgnore.class))
.map(FullyQualifiedMemberNameAndDesc::of),
stubClassMethods.stream()
).map(e -> new MemberInfo("unknown", e, false, false))
.collect(Collectors.toList()),
unmatched
);
} catch (IOException e) {
throw new UncheckedIOException("Failed to compare version " + v, e);
}
Expand All @@ -258,6 +257,7 @@ public static void main(String[] args) throws IOException, URISyntaxException {
private static void writeList(List<MemberInfo> missing, Path outputFile) throws IOException {
Files.createDirectories(outputFile.getParent());
Files.deleteIfExists(outputFile);
if (missing.isEmpty()) return;
var byModule = new HashMap<String, List<String>>();
for (var stub : missing) {
String sta = stub.isStatic() ? "; static" : ";";
Expand Down Expand Up @@ -365,7 +365,8 @@ public static void compare(List<Path> moduleHolders, Map<String, Pair<String, Cl
}
var isStatic = (m.access & Opcodes.ACC_STATIC) != 0;
var isAbstract = (m.access & Opcodes.ACC_ABSTRACT) != 0;
methods.remove(new MemberInfo(modName, new FullyQualifiedMemberNameAndDesc(ct, m.name, Type.getMethodType(m.desc)), isAbstract, isStatic));
methods.remove(new MemberInfo(modName, new FullyQualifiedMemberNameAndDesc(
ct, m.name, Type.getMethodType(m.desc)), isAbstract, isStatic));
}

// check if method(s) still exist on parent (include interfaces in traversal)
Expand Down Expand Up @@ -410,6 +411,11 @@ public static void compare(List<Path> moduleHolders, Map<String, Pair<String, Cl
}
} catch (IOException e) {
throw new UncheckedIOException("Failed to read " + p.toAbsolutePath(), e);
} catch (RuntimeException e) {
if (p.toString().endsWith("/module-info.sig")) {
// ASM library may fail to read some module-info.sig
System.err.println("Failed to read " + p.toAbsolutePath());
} else throw new RuntimeException("Failed to read " + p.toAbsolutePath(), e);
}
});
} catch (IOException e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package xyz.wagyourtail.jvmdg.j22.stub.java_base;

import xyz.wagyourtail.jvmdg.version.Ref;
import xyz.wagyourtail.jvmdg.version.Stub;

public class J_L_Module {
@Stub(ref = @Ref("java/lang/Module"))
public static boolean isNativeAccessEnabled(Module module) {
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package xyz.wagyourtail.jvmdg.j9.intl.module;

import xyz.wagyourtail.jvmdg.j9.stub.java_base.J_L_M_ModuleDescriptor;
import xyz.wagyourtail.jvmdg.j9.stub.java_base.J_L_Module;
import xyz.wagyourtail.jvmdg.j9.stub.java_base.J_L_ModuleLayer;

import java.util.*;

public class ModuleConstantHelper {
private static final Map<String, J_L_Module> MODULES = new HashMap<>();
private static final Map<String, J_L_Module> MODULES_FROM_PACKAGE = new HashMap<>();
private static final ClassLoader ORIGINAL_SYSTEM_CLASS_LOADER = ClassLoader.getSystemClassLoader();
public static final J_L_ModuleLayer BOOT_LAYER =
// Note: This field is in this class as it's initialization is execution order sensitive as it need
// to be loaded after "MODULES" HashMap is initialized, but before initializing any boot "Module"
new J_L_ModuleLayer(Collections.emptyList(), MODULES);

static {
// TODO: Auto generate this data in a separate "ModuleConstants" class
registerBootModule("java.base", "java.io", "java.lang", "java.math",
"java.net", "java.nio", "java.security", "java.text", "java.time", "java.util",
"javax.crypto", "javax.net", "javax.security");
registerBootModule("java.logging", "java.util.logging");
registerBootModule("java.net.http", "java.net.http");
registerBootModule("jdk.httpserver", "com.sun.net.httpserver");
registerBootModule("jdk.jfr", "jdk.jfr");
}

private static void registerBootModule(String name, String... packages) {
J_L_M_ModuleDescriptor descriptor = new J_L_M_ModuleDescriptor.Builder(name, false, Collections.emptySet())
.packages(new HashSet<>(Arrays.asList(packages))).build();
J_L_Module module = new J_L_Module(ORIGINAL_SYSTEM_CLASS_LOADER, BOOT_LAYER, descriptor);
MODULES.put(name, module);
for (String packageName : packages) {
MODULES_FROM_PACKAGE.put(packageName, module);
}
}

public static J_L_Module bootModuleFromClass(Class<?> clazz) {
boolean bootClassLoader;
if ((bootClassLoader = clazz.getClassLoader() == null) ||
clazz.getClassLoader() == ORIGINAL_SYSTEM_CLASS_LOADER) {
J_L_Module module = bootModuleFromClassName(clazz.getName());
// Unnamed modules must have a class loader
// but on java8, the boot class loader is null
// Making Object.class.getClassLoader() return null on java8
if (module == null && bootClassLoader) {
return MODULES.get("java.base");
}
return module;
}
return null;
}

// Return null to make JvmDowngrader use
public static J_L_Module bootModuleFromClassName(String className) {
String packageName = className;
while (true) {
int pkgEnd = packageName.lastIndexOf('.');
if (pkgEnd == -1) return null;
packageName = packageName.substring(0, pkgEnd);
J_L_Module module = MODULES_FROM_PACKAGE.get(packageName);
if (module != null) return module;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package xyz.wagyourtail.jvmdg.j9.intl.module;

import xyz.wagyourtail.jvmdg.j9.stub.java_base.J_L_M_ModuleDescriptor;
import xyz.wagyourtail.jvmdg.j9.stub.java_base.J_L_M_ModuleFinder;
import xyz.wagyourtail.jvmdg.j9.stub.java_base.J_L_M_ModuleReference;

import java.util.Collections;
import java.util.Optional;
import java.util.Set;

public class ModuleFinderImpl implements J_L_M_ModuleFinder {
public static final ModuleFinderImpl EMPTY = new ModuleFinderImpl(Collections.emptySet());
private final Set<J_L_M_ModuleReference> moduleReferences;

public ModuleFinderImpl(Set<J_L_M_ModuleReference> moduleReferences) {
this.moduleReferences = moduleReferences;
}

@Override
public Optional<J_L_M_ModuleReference> find(String name) {
for (J_L_M_ModuleReference moduleReference : this.moduleReferences) {
J_L_M_ModuleDescriptor descriptor = moduleReference.descriptor();
if (descriptor != null && descriptor.name().equals(name)) {
return Optional.of(moduleReference);
}
}
return Optional.empty();
}

@Override
public Set<J_L_M_ModuleReference> findAll() {
return this.moduleReferences;
}
}
Original file line number Diff line number Diff line change
@@ -1,30 +1,20 @@
package xyz.wagyourtail.jvmdg.j9.stub.java_base;


import xyz.wagyourtail.jvmdg.j9.intl.module.ModuleConstantHelper;
import xyz.wagyourtail.jvmdg.version.Ref;
import xyz.wagyourtail.jvmdg.version.Stub;

import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;

public class J_L_Class {
private static final Map<ClassLoader, J_L_Module> moduleCache = Collections.synchronizedMap(new WeakHashMap<>());

@Stub(ref = @Ref("Ljava/lang/Class;"))
public static Class<?> forName(J_L_Module module, String name) throws ClassNotFoundException {
return Class.forName(name, true, module.getClassLoader());
}

@Stub
public static J_L_Module getModule(Class<?> clazz) {
ClassLoader loader = clazz.getClassLoader();
J_L_Module module = moduleCache.get(loader);
if (module == null) {
module = new J_L_Module(loader);
moduleCache.put(loader, module);
}
return module;
J_L_Module module = ModuleConstantHelper.bootModuleFromClass(clazz);
return module != null ? module :
J_L_ClassLoader.getUnnamedModule(clazz.getClassLoader());
}

@Stub
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

public class J_L_ClassLoader {
private static final Map<ClassLoader, String> nameMap = Collections.synchronizedMap(new WeakHashMap<>());
private static final Map<ClassLoader, J_L_Module> unnamedModuleMap = Collections.synchronizedMap(new WeakHashMap<>());

@Modify(ref = @Ref(value = "Ljava/lang/ClassLoader;", member = "<init>", desc = "(Ljava/lang/String;Ljava/lang/ClassLoader;)V"))
public static void init(MethodNode mnode, int i) {
Expand Down Expand Up @@ -63,7 +64,7 @@ public static String getName(ClassLoader classLoader) {

@Stub
public static J_L_Module getUnnamedModule(ClassLoader classLoader) {
return new J_L_Module(classLoader);
return unnamedModuleMap.computeIfAbsent(classLoader, J_L_Module::new);
}

@Stub(ref = @Ref("Ljava/lang/ClassLoader;"))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package xyz.wagyourtail.jvmdg.j9.stub.java_base;

import xyz.wagyourtail.jvmdg.version.Adapter;

@Adapter("java/lang/IllegalCallerException")
public class J_L_IllegalCallerException extends RuntimeException {
public J_L_IllegalCallerException() {
super();
}

public J_L_IllegalCallerException(String s) {
super(s);
}

public J_L_IllegalCallerException(Throwable cause) {
super(cause);
}

public J_L_IllegalCallerException(String message, Throwable cause) {
super(message, cause);
}
}
Loading

0 comments on commit 747ca0a

Please sign in to comment.