feat: Introduce black-reflection and compiler modules, integrate reflection utilities, and update core components.

This commit is contained in:
alex5402
2026-01-30 18:24:57 +05:30
parent 5a557f1521
commit e779247466
70 changed files with 2424 additions and 6069 deletions
@@ -0,0 +1,15 @@
package top.niunaijun.blackreflection;
/**
* on 2022/2/16.
* * ∧_∧
* (`・ω・∥
* 丶 つ0
* しーJ
* 此处无Bug
*/
public class BlackNullPointerException extends NullPointerException {
public BlackNullPointerException(String s) {
super(s);
}
}
@@ -0,0 +1,245 @@
package top.niunaijun.blackreflection;
import java.lang.annotation.Annotation;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
import top.niunaijun.blackreflection.annotation.BClass;
import top.niunaijun.blackreflection.annotation.BClassName;
import top.niunaijun.blackreflection.annotation.BClassNameNotProcess;
import top.niunaijun.blackreflection.annotation.BConstructor;
import top.niunaijun.blackreflection.annotation.BConstructorNotProcess;
import top.niunaijun.blackreflection.annotation.BField;
import top.niunaijun.blackreflection.annotation.BFieldCheckNotProcess;
import top.niunaijun.blackreflection.annotation.BFieldNotProcess;
import top.niunaijun.blackreflection.annotation.BFieldSetNotProcess;
import top.niunaijun.blackreflection.annotation.BMethodCheckNotProcess;
import top.niunaijun.blackreflection.annotation.BParamClass;
import top.niunaijun.blackreflection.annotation.BParamClassName;
import top.niunaijun.blackreflection.utils.Reflector;
@SuppressWarnings("unchecked")
public class BlackReflection {
public static boolean DEBUG = false;
public static boolean CACHE = false;
private static final Map<Class<?>, Object> sProxyCache = new HashMap<>();
private static final Map<Class<?>, Object> sProxyWithExceptionCache = new HashMap<>();
// key caller
private static final WeakHashMap<Object, Map<Class<?>, Object>> sCallerProxyCache = new WeakHashMap<>();
// public static <T> T create(Class<T> clazz, final Object caller) {
// return create(clazz, caller, false);
// }
public static <T> T create(Class<T> clazz, final Object caller, boolean withException) {
try {
T proxy = getProxy(clazz, caller, withException);
if (proxy != null)
return proxy;
final WeakReference<Object> weakCaller = caller == null ? null : new WeakReference<>(caller);
final Class<?> aClass = getClassNameByBlackClass(clazz);
Object o = Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String name = method.getName();
Class<?> returnType = method.getReturnType();
try {
boolean isStatic = weakCaller == null;
Object callerByWeak = isStatic ? null : weakCaller.get();
// fidel
BField bField = method.getAnnotation(BField.class);
BFieldNotProcess bFieldNotProcess = method.getAnnotation(BFieldNotProcess.class);
if (bField != null || bFieldNotProcess != null) {
Object call;
Reflector on = Reflector.on(aClass).field(name);
if (isStatic) {
call = on.get();
} else {
if (callerByWeak == null) {
return generateNullValue(returnType);
}
call = on.get(callerByWeak);
}
return call;
}
// void
BFieldSetNotProcess bFieldSetNotProcess = method.getAnnotation(BFieldSetNotProcess.class);
if (bFieldSetNotProcess != null) {
// startsWith "_set_"
name = name.substring("_set_".length());
Reflector on = Reflector.on(aClass).field(name);
if (isStatic) {
on.set(args[0]);
} else {
if (callerByWeak == null) {
return 0;
}
on.set(callerByWeak, args[0]);
}
return 0;
}
// check field
BFieldCheckNotProcess bFieldCheckNotProcess = method.getAnnotation(BFieldCheckNotProcess.class);
if (bFieldCheckNotProcess != null) {
// startsWith "_check_"
name = name.substring("_check_".length());
try {
Reflector on = Reflector.on(aClass).field(name);
return on.getField();
} catch (Throwable ignored) {
return null;
}
}
Class<?>[] paramClass = getParamClass(method);
// check method
BMethodCheckNotProcess bMethodCheckNotProcess = method.getAnnotation(BMethodCheckNotProcess.class);
if (bMethodCheckNotProcess != null) {
// startsWith "_check_"
name = name.substring("_check_".length());
try {
return Reflector.on(aClass).method(name, paramClass).getMethod();
} catch (Throwable ignored) {
return null;
}
}
// method
BConstructor bConstructor = method.getAnnotation(BConstructor.class);
BConstructorNotProcess bConstructorNotProcess = method.getAnnotation(BConstructorNotProcess.class);
if (bConstructor != null || bConstructorNotProcess != null) {
Reflector on = Reflector.on(aClass).constructor(paramClass);
return on.newInstance(args);
}
Object call;
Reflector on = Reflector.on(aClass).method(name, paramClass);
if (isStatic) {
call = on.call(args);
} else {
if (callerByWeak == null) {
return generateNullValue(returnType);
}
call = on.callByCaller(callerByWeak, args);
}
return call;
} catch (Throwable throwable) {
if (DEBUG) {
if (throwable.getCause() != null) {
throwable.getCause().printStackTrace();
} else {
throwable.printStackTrace();
}
}
if (throwable instanceof BlackNullPointerException) {
throw new NullPointerException(throwable.getMessage());
}
if (withException) {
throw throwable;
}
}
return generateNullValue(returnType);
}
});
if (caller == null) {
if (withException) {
sProxyWithExceptionCache.put(clazz, o);
} else {
sProxyCache.put(clazz, o);
}
}
return (T) o;
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
private static <T> T getProxy(Class<T> clazz, final Object caller, boolean withException) {
try {
if (caller == null) {
Object o;
if (withException) {
o = sProxyWithExceptionCache.get(clazz);
} else {
o = sProxyCache.get(clazz);
}
if (o != null) {
return (T) o;
}
}
} catch (Throwable ignore) {
}
return null;
}
private static Class<?>[] getParamClass(Method method) throws Throwable {
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
Class<?>[] parameterTypes = method.getParameterTypes();
Class<?>[] param = new Class[parameterTypes.length];
for (int i = 0; i < parameterTypes.length; i++) {
Annotation[] parameterAnnotation = parameterAnnotations[i];
boolean found = false;
for (Annotation annotation : parameterAnnotation) {
if (annotation instanceof BParamClassName) {
found = true;
param[i] = Class.forName(((BParamClassName) annotation).value());
break;
} else if (annotation instanceof BParamClass) {
found = true;
param[i] = ((BParamClass) annotation).value();
break;
}
}
if (!found) {
param[i] = parameterTypes[i];
}
}
return param;
}
private static Class<?> getClassNameByBlackClass(Class<?> clazz) throws ClassNotFoundException {
BClass bClass = clazz.getAnnotation(BClass.class);
BClassName bClassName = clazz.getAnnotation(BClassName.class);
BClassNameNotProcess bClassNameNotProcess = clazz.getAnnotation(BClassNameNotProcess.class);
if (bClass == null && bClassName == null && bClassNameNotProcess == null) {
throw new RuntimeException("Not found @BlackClass or @BlackStrClass");
}
if (bClass != null) {
return bClass.value();
} else if (bClassName != null) {
return Class.forName(bClassName.value());
} else {
return Class.forName(bClassNameNotProcess.value());
}
}
private static Object generateNullValue(Class<?> returnType) {
if (returnType == void.class) {
return 0;
}
if (returnType.isPrimitive()) {
throw new BlackNullPointerException("value is null!");
}
return null;
}
}
@@ -0,0 +1,14 @@
package top.niunaijun.blackreflection.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Retention(RUNTIME)
@Target({TYPE})
public @interface BClass {
Class<?> value();
}
@@ -0,0 +1,14 @@
package top.niunaijun.blackreflection.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Retention(RUNTIME)
@Target({TYPE})
public @interface BClassName {
String value();
}
@@ -0,0 +1,14 @@
package top.niunaijun.blackreflection.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Retention(RUNTIME)
@Target({TYPE})
public @interface BClassNameNotProcess {
String value();
}
@@ -0,0 +1,21 @@
package top.niunaijun.blackreflection.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* on 2022/2/16.
* * ∧_∧
* (`・ω・∥
* 丶 つ0
* しーJ
* 此处无Bug
*/
@Retention(RUNTIME)
@Target({METHOD})
public @interface BConstructor {
}
@@ -0,0 +1,21 @@
package top.niunaijun.blackreflection.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* on 2022/2/16.
* * ∧_∧
* (`・ω・∥
* 丶 つ0
* しーJ
* 此处无Bug
*/
@Retention(RUNTIME)
@Target({METHOD})
public @interface BConstructorNotProcess {
}
@@ -0,0 +1,14 @@
package top.niunaijun.blackreflection.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Retention(RUNTIME)
@Target({METHOD})
public @interface BField {
}
@@ -0,0 +1,13 @@
package top.niunaijun.blackreflection.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Retention(RUNTIME)
@Target({METHOD})
public @interface BFieldCheckNotProcess {
}
@@ -0,0 +1,15 @@
package top.niunaijun.blackreflection.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Retention(RUNTIME)
@Target({METHOD})
public @interface BFieldNotProcess {
}
@@ -0,0 +1,13 @@
package top.niunaijun.blackreflection.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Retention(RUNTIME)
@Target({METHOD})
public @interface BFieldSetNotProcess {
}
@@ -0,0 +1,13 @@
package top.niunaijun.blackreflection.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Retention(RUNTIME)
@Target({METHOD})
public @interface BMethod {
}
@@ -0,0 +1,13 @@
package top.niunaijun.blackreflection.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Retention(RUNTIME)
@Target({METHOD})
public @interface BMethodCheckNotProcess {
}
@@ -0,0 +1,15 @@
package top.niunaijun.blackreflection.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Retention(RUNTIME)
@Target({PARAMETER})
public @interface BParamClass {
Class<?> value();
}
@@ -0,0 +1,14 @@
package top.niunaijun.blackreflection.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Retention(RUNTIME)
@Target({PARAMETER})
public @interface BParamClassName {
String value();
}
@@ -0,0 +1,13 @@
package top.niunaijun.blackreflection.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Retention(RUNTIME)
@Target({METHOD})
public @interface BStaticField {
}
@@ -0,0 +1,13 @@
package top.niunaijun.blackreflection.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Retention(RUNTIME)
@Target({METHOD})
public @interface BStaticMethod {
}
@@ -0,0 +1,39 @@
package top.niunaijun.blackreflection.utils;
import top.niunaijun.blackreflection.annotation.BClass;
import top.niunaijun.blackreflection.annotation.BClassName;
import top.niunaijun.blackreflection.annotation.BClassNameNotProcess;
/**
* on 2022/2/18.
* * ∧_∧
* (`・ω・∥
* 丶 つ0
* しーJ
* 此处无Bug
*/
public class ClassUtil {
public static Class<?> classReady(Class<?> clazz) {
BClassNameNotProcess bClassNameNotProcess = clazz.getAnnotation(BClassNameNotProcess.class);
if (bClassNameNotProcess != null) {
return classReady(bClassNameNotProcess.value());
}
BClass annotation = clazz.getAnnotation(BClass.class);
if (annotation != null) {
return annotation.value();
}
BClassName bClassName = clazz.getAnnotation(BClassName.class);
if (bClassName != null) {
return classReady(bClassName.value());
}
return null;
}
private static Class<?> classReady(String clazz) {
try {
return Class.forName(clazz);
} catch (ClassNotFoundException ignored) {
}
return null;
}
}
@@ -0,0 +1,440 @@
package top.niunaijun.blackreflection.utils;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class Reflector {
public static final String LOG_TAG ="Reflector";
protected Class<?> mType;
protected Object mCaller;
protected Constructor<?> mConstructor;
protected Field mField;
protected Method mMethod;
public static Reflector on(String name) throws Exception {
return on(name, true, Reflector.class.getClassLoader());
}
public static Reflector on(String name, boolean initialize) throws Exception {
return on(name, initialize, Reflector.class.getClassLoader());
}
public static Reflector on(String name, boolean initialize, ClassLoader loader) throws Exception {
try {
return on(Class.forName(name, initialize, loader));
} catch (Throwable e) {
throw new Exception("Oops!", e);
}
}
public static Reflector on(Class<?> type) {
Reflector reflector = new Reflector();
reflector.mType = type;
return reflector;
}
public static Reflector with(Object caller) throws Exception {
return on(caller.getClass()).bind(caller);
}
protected Reflector() {
}
public Reflector constructor(Class<?>... parameterTypes) throws Exception {
try {
mConstructor = mType.getDeclaredConstructor(parameterTypes);
mConstructor.setAccessible(true);
mField = null;
mMethod = null;
return this;
} catch (Throwable e) {
throw new Exception("Oops!", e);
}
}
@SuppressWarnings("unchecked")
public <R> R newInstance(Object... initargs) throws Exception {
if (mConstructor == null) {
throw new Exception("Constructor was null!");
}
try {
return (R) mConstructor.newInstance(initargs);
} catch (InvocationTargetException e) {
throw new Exception("Oops!", e.getTargetException());
} catch (Throwable e) {
throw new Exception("Oops!", e);
}
}
protected Object checked(Object caller) throws Exception {
if (caller == null || mType.isInstance(caller)) {
return caller;
}
throw new Exception("Caller [" + caller + "] is not a instance of type [" + mType + "]!");
}
protected void check(Object caller, Member member, String name) throws Exception {
if (member == null) {
throw new Exception(name + " was null!");
}
if (caller == null && !Modifier.isStatic(member.getModifiers())) {
throw new Exception("Need a caller!");
}
checked(caller);
}
public Reflector bind(Object caller) throws Exception {
mCaller = checked(caller);
return this;
}
public Reflector unbind() {
mCaller = null;
return this;
}
public Reflector field(String name) throws Exception {
try {
mField = findField(name);
mField.setAccessible(true);
mConstructor = null;
mMethod = null;
return this;
} catch (Throwable e) {
throw new Exception("Oops!", e);
}
}
public Field getField() {
return mField;
}
protected Field findField(String name) throws NoSuchFieldException {
try {
return mType.getField(name);
} catch (NoSuchFieldException e) {
for (Class<?> cls = mType; cls != null; cls = cls.getSuperclass()) {
try {
return cls.getDeclaredField(name);
} catch (NoSuchFieldException ex) {
// Ignored
}
}
throw e;
}
}
@SuppressWarnings("unchecked")
public <R> R get() throws Exception {
return get(mCaller);
}
@SuppressWarnings("unchecked")
public <R> R get(Object caller) throws Exception {
check(caller, mField, "Field");
try {
return (R) mField.get(caller);
} catch (Throwable e) {
throw new Exception("Oops!", e);
}
}
public Reflector set(Object value) throws Exception {
return set(mCaller, value);
}
public Reflector set(Object caller, Object value) throws Exception {
check(caller, mField, "Field");
try {
mField.set(caller, value);
return this;
} catch (Throwable e) {
throw new Exception("Oops!", e);
}
}
public Reflector method(String name, Class<?>... parameterTypes) throws Exception {
try {
mMethod = findMethod(name, parameterTypes);
mMethod.setAccessible(true);
mConstructor = null;
mField = null;
return this;
} catch (NoSuchMethodException e) {
throw new Exception("Oops!", e);
}
}
public Method getMethod() {
return mMethod;
}
protected Method findMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException {
try {
return mType.getMethod(name, parameterTypes);
} catch (NoSuchMethodException e) {
for (Class<?> cls = mType; cls != null; cls = cls.getSuperclass()) {
try {
return cls.getDeclaredMethod(name, parameterTypes);
} catch (NoSuchMethodException ex) {
// Ignored
}
}
throw e;
}
}
public <R> R call(Object... args) throws Exception {
return callByCaller(mCaller, args);
}
@SuppressWarnings("unchecked")
public <R> R callByCaller(Object caller, Object... args) throws Exception {
check(caller, mMethod, "Method");
try {
return (R) mMethod.invoke(caller, args);
} catch (InvocationTargetException e) {
throw new Exception("Oops!", e.getTargetException());
} catch (Throwable e) {
throw new Exception("Oops!", e);
}
}
public static class QuietReflector extends Reflector {
protected Throwable mIgnored;
public static QuietReflector on(String name) {
return on(name, true, QuietReflector.class.getClassLoader());
}
public static QuietReflector on(String name, boolean initialize) {
return on(name, initialize, QuietReflector.class.getClassLoader());
}
public static QuietReflector on(String name, boolean initialize, ClassLoader loader) {
Class<?> cls = null;
try {
cls = Class.forName(name, initialize, loader);
return on(cls, null);
} catch (Throwable e) {
// Log.w(LOG_TAG, "Oops!", e);
return on(cls, e);
}
}
public static QuietReflector on(Class<?> type) {
return on(type, (type == null) ? new Exception("Type was null!") : null);
}
private static QuietReflector on(Class<?> type, Throwable ignored) {
QuietReflector reflector = new QuietReflector();
reflector.mType = type;
reflector.mIgnored = ignored;
return reflector;
}
public static QuietReflector with(Object caller) {
if (caller == null) {
return on((Class<?>) null);
}
return on(caller.getClass()).bind(caller);
}
protected QuietReflector() {
}
public Throwable getIgnored() {
return mIgnored;
}
protected boolean skip() {
return skipAlways() || mIgnored != null;
}
protected boolean skipAlways() {
return mType == null;
}
@Override
public QuietReflector constructor(Class<?>... parameterTypes) {
if (skipAlways()) {
return this;
}
try {
mIgnored = null;
super.constructor(parameterTypes);
} catch (Throwable e) {
mIgnored = e;
// Log.w(LOG_TAG, "Oops!", e);
}
return this;
}
@Override
public <R> R newInstance(Object... initargs) {
if (skip()) {
return null;
}
try {
mIgnored = null;
return super.newInstance(initargs);
} catch (Throwable e) {
mIgnored = e;
// Log.w(LOG_TAG, "Oops!", e);
}
return null;
}
@Override
public QuietReflector bind(Object obj) {
if (skipAlways()) {
return this;
}
try {
mIgnored = null;
super.bind(obj);
} catch (Throwable e) {
mIgnored = e;
// Log.w(LOG_TAG, "Oops!", e);
}
return this;
}
@Override
public QuietReflector unbind() {
super.unbind();
return this;
}
@Override
public QuietReflector field(String name) {
if (skipAlways()) {
return this;
}
try {
mIgnored = null;
super.field(name);
} catch (Throwable e) {
mIgnored = e;
// Log.w(LOG_TAG, "Oops!", e);
}
return this;
}
@Override
public <R> R get() {
if (skip()) {
return null;
}
try {
mIgnored = null;
return super.get();
} catch (Throwable e) {
mIgnored = e;
// Log.w(LOG_TAG, "Oops!", e);
}
return null;
}
@Override
public <R> R get(Object caller) {
if (skip()) {
return null;
}
try {
mIgnored = null;
return super.get(caller);
} catch (Throwable e) {
mIgnored = e;
// Log.w(LOG_TAG, "Oops!", e);
}
return null;
}
@Override
public QuietReflector set(Object value) {
if (skip()) {
return this;
}
try {
mIgnored = null;
super.set(value);
} catch (Throwable e) {
mIgnored = e;
// Log.w(LOG_TAG, "Oops!", e);
}
return this;
}
@Override
public QuietReflector set(Object caller, Object value) {
if (skip()) {
return this;
}
try {
mIgnored = null;
super.set(caller, value);
} catch (Throwable e) {
mIgnored = e;
// Log.w(LOG_TAG, "Oops!", e);
}
return this;
}
@Override
public QuietReflector method(String name, Class<?>... parameterTypes) {
if (skipAlways()) {
return this;
}
try {
mIgnored = null;
super.method(name, parameterTypes);
} catch (Throwable e) {
mIgnored = e;
// Log.w(LOG_TAG, "Oops!", e);
}
return this;
}
@Override
public <R> R call(Object... args) {
if (skip()) {
return null;
}
try {
mIgnored = null;
return super.call(args);
} catch (Throwable e) {
mIgnored = e;
// Log.w(LOG_TAG, "Oops!", e);
}
return null;
}
@Override
public <R> R callByCaller(Object caller, Object... args) {
if (skip()) {
return null;
}
try {
mIgnored = null;
return super.callByCaller(caller, args);
} catch (Throwable e) {
mIgnored = e;
// Log.w(LOG_TAG, "Oops!", e);
}
return null;
}
}
}