Created
December 3, 2019 16:43
-
-
Save tabjy/8a46fbfe873af81b77bfb9b70de52422 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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