Skip to content

Instantly share code, notes, and snippets.

@tabjy
Created December 3, 2019 16:43
Show Gist options
  • Save tabjy/8a46fbfe873af81b77bfb9b70de52422 to your computer and use it in GitHub Desktop.
Save tabjy/8a46fbfe873af81b77bfb9b70de52422 to your computer and use it in GitHub Desktop.
package org.openjdk.jmc.agent.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
// polyfill for pre-11 nest-based access control
public class NestBasedAccess {
private static int bar = 42;
public static class InnerClass {
static void foo() {
bar = 42;
}
public class InnerInnerClass {}
}
public static void main(String[] args) {
System.out.println(isNestMateOf(NestBasedAccess.class, InnerClass.class));
}
public static Class<?>[] getNestMembers(Class<?> clazz) {
// String version = System.getProperty("java.version");
// if (Integer.parseInt(version.substring(0, version.indexOf("."))) >= 11) {
// try {
// return (Class<?>[]) Class.class.getMethod("getNestMembers", null).invoke(clazz, null);
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
// throw new RuntimeException(e); // this should not happen
// }
// }
// polyfill for pre-11 api
List<Class<?>> classes = new ArrayList<>();
classes.add(getNestHost(clazz));
int i = 0;
while (i < classes.size()) {
classes.addAll(Arrays.asList(classes.get(i).getDeclaredClasses()));
i++;
}
return classes.toArray(new Class[0]);
}
// private static List<Class<?>> getInnerClasses(Class<?> clazz) {
// final ClassLoader cl = clazz.getClassLoader() != null ? clazz.getClassLoader() : ClassLoader.getSystemClassLoader();
// InputStream is = cl.getResourceAsStream(TypeUtils.getInternalName(clazz.getName()) + ".class");
// if (is == null) {
// return Collections.emptyList();
// }
//
// // TODO: remove duplicates
// ByteArrayOutputStream buffer = new ByteArrayOutputStream();
// int nRead;
// byte[] data = new byte[1024]; // 1024 is chosen arbitrarily
// try {
// while ((nRead = is.read(data, 0, data.length)) != -1) {
// buffer.write(data, 0, nRead);
// buffer.flush();
// }
// } catch (IOException e) {
// throw new RuntimeException(e);
// }
//
// byte[] bytes = buffer.toByteArray();
//
// ClassReader cr = new ClassReader(bytes);
//
// final List<Class<?>> ret = new ArrayList<>();
// cr.accept(new ClassVisitor(Opcodes.ASM5) {
// @Override
// public void visitInnerClass(String name, String outerName, String innerName, int access) {
// super.visitInnerClass(name, outerName, innerName, access);
//
// try {
// ret.add(cl.loadClass(TypeUtils.getCanonicalName(innerName)));
// } catch (ClassNotFoundException e) {
// e.printStackTrace(); // TODO: figure out what to do with this exception
// }
// }
// }, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
//
// return ret;
// }
public static boolean isNestMateOf(Class<?> lhs, Class<?> rhs) {
// String version = System.getProperty("java.version");
// if (Integer.parseInt(version.substring(0, version.indexOf("."))) >= 11) {
// try {
// return (Boolean) Class.class.getMethod("isNestmateOf", Class.class).invoke(lhs, rhs);
// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
// throw new RuntimeException(e); // this should not happen
// }
// }
// polyfill for pre-11 api
return getNestHost(lhs).equals(getNestHost(rhs));
}
public static Class<?> getNestHost(Class<?> clazz) {
// String version = System.getProperty("java.version");
// if (Integer.parseInt(version.substring(0, version.indexOf("."))) >= 11) {
// try {
// return (Class<?>) Class.class.getMethod("getNestHost", null).invoke(clazz, null);
// } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
// throw new RuntimeException(e); // this should not happen
// }
// }
//
// // polyfill for pre-11 api
// array types, primitive types, and void belong to the nests consisting only of theme, and are the nest hosts.
if (clazz.isArray()) {
return clazz;
}
if (clazz.isPrimitive()) {
return clazz;
}
if (Void.class.equals(clazz)) {
return clazz;
}
// For pre-11 java there is no real nest hosts. So I just take the outer-most class for consistence.
while (true) {
if (clazz.getEnclosingClass() == null) {
return clazz;
}
clazz = clazz.getEnclosingClass();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment