下面列出了org.objectweb.asm.Opcodes# ACC_PUBLIC 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private FieldNode injectFieldAndGetter(ClassNode classNode) {
FieldNode field = new FieldNode(Opcodes.ACC_PUBLIC, "wrapper",
"L" + getWrapperName() + ";", "L" + getWrapperName() + ";", null);
classNode.fields.add(field);
MethodNode getter = new MethodNode(Opcodes.ACC_PUBLIC, "getWrapper",
"()L" + getWrapperName() + ";", null, null);
getter.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
getter.instructions.add(new FieldInsnNode(Opcodes.GETFIELD, classNode.name,
field.name, field.desc));
getter.instructions.add(new InsnNode(Opcodes.ARETURN));
getter.visitEnd();
getter.visitMaxs(1, 1);
classNode.methods.add(getter);
return field;
}
private static void defineSuperAccessorMethod(ClassWriter cw, java.lang.reflect.Method method, Type superType,
String superAccessorMethodSuffix)
{
Method originalAsmMethod = Method.getMethod(method);
Method newAsmMethod = new Method(method.getName() + superAccessorMethodSuffix,
originalAsmMethod.getReturnType(),
originalAsmMethod.getArgumentTypes());
GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, newAsmMethod, null, null, cw);
mg.visitCode();
// call super method
mg.loadThis();
mg.loadArgs();
mg.visitMethodInsn(Opcodes.INVOKESPECIAL,
superType.getInternalName(),
method.getName(),
Type.getMethodDescriptor(method),
false);
mg.returnValue();
// finish the method
mg.endMethod();
mg.visitMaxs(10, 10);
mg.visitEnd();
}
private FieldNode injectFieldAndGetter(ClassNode classNode) {
FieldNode field = new FieldNode(Opcodes.ACC_PUBLIC, "type",
"L" + GameObjectType.class.getCanonicalName().replaceAll("\\.", "/") + ";", "L" + GameObjectType.class.getCanonicalName().replaceAll("\\.", "/") + ";", null);
classNode.fields.add(field);
MethodNode getter = new MethodNode(Opcodes.ACC_PUBLIC, "getType",
"()L" + GameObjectType.class.getCanonicalName().replaceAll("\\.", "/") + ";", null, null);
getter.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
getter.instructions.add(new FieldInsnNode(Opcodes.GETFIELD, classNode.name,
field.name, field.desc));
getter.instructions.add(new InsnNode(Opcodes.ARETURN));
getter.visitEnd();
getter.visitMaxs(1, 1);
classNode.methods.add(getter);
return field;
}
private String renameMethod(MethodNode methodToRename) {
// first remove any annotations from renamed base methods
AnnotationUtils.clearMethodAnnotations(methodToRename);
// rename the method
String originalMethodName = methodToRename.name;
String renamedMethodName = mergeRenamePrefix + methodToRename.name;
methodToRename.name = renamedMethodName;
// make the method private to hide it from the end user
methodToRename.access = methodToRename.access & (~Opcodes.ACC_PUBLIC & ~Opcodes.ACC_PROTECTED & ~Opcodes.ACC_PRIVATE);
methodToRename.access = methodToRename.access | Opcodes.ACC_PRIVATE;
Log.info("Renamed " + originalMethodName + " to " + renamedMethodName);
return originalMethodName; // return the original name
}
@Override
public void visitEnd() {
if (instrumentationActions.isJUnit4RuleInjectionRequired) {
FieldVisitor fv = super.visitField(Opcodes.ACC_PUBLIC, "scottReportingRule", Type.getDescriptor(ScottReportingRule.class), null, null);
fv.visitAnnotation(Type.getDescriptor(Rule.class), true).visitEnd();
}
if (instrumentationActions.isJUnit5ExtensionInjectionRequired) {
AnnotationVisitor av0 = super.visitAnnotation("Lorg/junit/jupiter/api/extension/ExtendWith;", true);
AnnotationVisitor av1 = av0.visitArray("value");
av1.visit(null, Type.getType("Lhu/advancedweb/scott/runtime/ScottJUnit5Extension;"));
av1.visitEnd();
av0.visitEnd();
}
super.visitEnd();
}
private String renameMethod(MethodNode methodToRename) {
// first remove any annotations from renamed base methods
AnnotationUtils.clearMethodAnnotations(methodToRename);
// rename the method
String originalMethodName = methodToRename.name;
String renamedMethodName = mergeRenamePrefix + methodToRename.name;
methodToRename.name = renamedMethodName;
// make the method private to hide it from the end user
methodToRename.access = methodToRename.access & (~Opcodes.ACC_PUBLIC & ~Opcodes.ACC_PROTECTED & ~Opcodes.ACC_PRIVATE);
methodToRename.access = methodToRename.access | Opcodes.ACC_PRIVATE;
Log.info("Renamed " + originalMethodName + " to " + renamedMethodName);
return originalMethodName; // return the original name
}
private static void readClassIndex(
Map<ClassIndex, File> indexes, InputStream in, File file, boolean allowSuper)
throws IOException {
ClassReader classReader = new ClassReader(in);
String className = ClassNameUtils.replaceSlash(classReader.getClassName());
boolean projectOutput = file.isDirectory();
int access = classReader.getAccess();
boolean isPublic = (Opcodes.ACC_PUBLIC & access) == Opcodes.ACC_PUBLIC;
boolean isProtected = (Opcodes.ACC_PROTECTED & access) == Opcodes.ACC_PROTECTED;
boolean isInterface = (Opcodes.ACC_INTERFACE & access) == Opcodes.ACC_INTERFACE;
boolean isAnnotation = (Opcodes.ACC_ANNOTATION & access) == Opcodes.ACC_ANNOTATION;
boolean isSuper = false;
if (allowSuper) {
isSuper = (Opcodes.ACC_SUPER & access) == Opcodes.ACC_SUPER;
}
if (projectOutput || (isPublic || isProtected || isSuper)) {
String pkg = ClassNameUtils.getPackage(className);
boolean onlyClassName = !preloadClassPackages.contains(pkg);
ClassAnalyzeVisitor classAnalyzeVisitor =
new ClassAnalyzeVisitor(className, onlyClassName, false);
classReader.accept(classAnalyzeVisitor, 0);
ClassIndex classIndex = classAnalyzeVisitor.getClassIndex();
if (!classIndex.isAnonymous) {
classIndex.setInterface(isInterface);
classIndex.setAnnotation(isAnnotation);
indexes.put(classIndex, file);
if (!onlyClassName) {
innerCache.putIfAbsent(className, classAnalyzeVisitor.getMembers());
}
}
}
}
private void addCoverageProbeField() {
super.visitField(Opcodes.ACC_STATIC | Opcodes.ACC_FINAL | Opcodes.ACC_PUBLIC
| Opcodes.ACC_SYNTHETIC, CodeCoverageStore.PROBE_FIELD_NAME, "[Z", null,
null);
super.visitField(Opcodes.ACC_STATIC | Opcodes.ACC_FINAL | Opcodes.ACC_PUBLIC
| Opcodes.ACC_SYNTHETIC, CodeCoverageStore.PROBE_LENGTH_FIELD_NAME, "I",
null, this.probeCount + 1);
//If there is no <clinit>, then generate one that sets the probe field directly
if (!foundClinit) {
MethodVisitor clinitMv = this.cv
.visitMethod(Opcodes.ACC_STATIC, "<clinit>", "()V", null, null);
clinitMv.visitCode();
pushConstant(clinitMv, this.classId);
pushConstant(clinitMv, this.probeCount);
clinitMv
.visitMethodInsn(Opcodes.INVOKESTATIC, CodeCoverageStore.CLASS_NAME,
"getOrRegisterClassProbes", "(II)[Z", false);
clinitMv.visitFieldInsn(Opcodes.PUTSTATIC, className,
CodeCoverageStore.PROBE_FIELD_NAME, "[Z");
clinitMv.visitInsn(Opcodes.RETURN);
clinitMv.visitMaxs(0, 0);
clinitMv.visitEnd();
}
}
private void addNullCopier(){
String rawclsName = currentClass.peek();
MethodVisitor mv = super.visitMethod(Opcodes.ACC_PUBLIC, "copy", "(Lcom/concurnas/bootstrap/runtime/CopyTracker;Lcom/concurnas/bootstrap/runtime/CopyDefinition;)" + rawclsName, null, null);
mv.visitCode();
mv.visitInsn(ACONST_NULL);
mv.visitInsn(ARETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
/**
* @see org.jumbune.debugger.instrumentation.adapter.BaseAdapter#visitEnd()
*/
@Override
public void visitEnd() {
for (Object o : methods) {
MethodNode mn = (MethodNode) o;
// finding main method
if (InstrumentUtil.validateMethodName(mn.name, MAIN_METHOD)
&& Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC == mn.access
&& Type.getMethodDescriptor(Type.VOID_TYPE,
TYPE_STRING_ARRAY).equals(mn.desc)) {
LOGGER.debug(MessageFormat.format(InstrumentationMessageLoader
.getMessage(MessageConstants.MAIN_METHOD_FOUND),
getClassName()));
InsnList insnList = mn.instructions;
InsnList il = new InsnList();
il.add(loadClasses());
// insert as first instruction
insnList.insertBefore(insnList.getFirst(), il);
break;
}
mn.visitMaxs(0, 0);
}
accept(cv);
}
@SuppressWarnings("unused")
private static String getAccessModifiers(int access){
LinkedList<String> modifiers = new LinkedList<String>();
if((Opcodes.ACC_ABSTRACT & access) == Opcodes.ACC_ABSTRACT){
modifiers.add("abstract");
}
if((Opcodes.ACC_ANNOTATION & access) == Opcodes.ACC_ANNOTATION){
modifiers.add("annotation");
}
if((Opcodes.ACC_BRIDGE & access) == Opcodes.ACC_BRIDGE){
modifiers.add("bridge");
}
if((Opcodes.ACC_DEPRECATED & access) == Opcodes.ACC_DEPRECATED){
modifiers.add("deprecated");
}
if((Opcodes.ACC_ENUM & access) == Opcodes.ACC_ENUM){
modifiers.add("enum");
}
if((Opcodes.ACC_FINAL & access) == Opcodes.ACC_FINAL){
modifiers.add("final");
}
if((Opcodes.ACC_INTERFACE & access) == Opcodes.ACC_INTERFACE){
modifiers.add("interface");
}
if((Opcodes.ACC_MANDATED & access) == Opcodes.ACC_MANDATED){
modifiers.add("mandated");
}
if((Opcodes.ACC_NATIVE & access) == Opcodes.ACC_NATIVE){
modifiers.add("native");
}
if((Opcodes.ACC_PRIVATE & access) == Opcodes.ACC_PRIVATE){
modifiers.add("private");
}
if((Opcodes.ACC_PROTECTED & access) == Opcodes.ACC_PROTECTED){
modifiers.add("protected");
}
if((Opcodes.ACC_PUBLIC & access) == Opcodes.ACC_PUBLIC){
modifiers.add("public");
}
if((Opcodes.ACC_STATIC & access) == Opcodes.ACC_STATIC){
modifiers.add("static");
}
if((Opcodes.ACC_STRICT & access) == Opcodes.ACC_STRICT){
modifiers.add("strict");
}
if((Opcodes.ACC_SUPER & access) == Opcodes.ACC_SUPER){
modifiers.add("super");
}
if((Opcodes.ACC_SYNCHRONIZED & access) == Opcodes.ACC_SYNCHRONIZED){
modifiers.add("synchronized");
}
if((Opcodes.ACC_SYNTHETIC & access) == Opcodes.ACC_SYNTHETIC){
modifiers.add("synthetic");
}
if((Opcodes.ACC_TRANSIENT & access) == Opcodes.ACC_TRANSIENT){
modifiers.add("transient");
}
if((Opcodes.ACC_VARARGS & access) == Opcodes.ACC_VARARGS){
modifiers.add("varargs");
}
if((Opcodes.ACC_VOLATILE & access) == Opcodes.ACC_VOLATILE){
modifiers.add("volatile");
}
return modifiers.toString();
}
@Override
public MethodVisitor visitMethod(int access, final String name, final String desc, String signature, String[] exceptions) {
if (isAnnotation) {
return null;
}
boolean isSynthetic = (access & Opcodes.ACC_SYNTHETIC) != 0;
boolean isPackagePrivate = (access & (Opcodes.ACC_PRIVATE | Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) == 0;
if (isSynthetic) {
final boolean isAccessor = isPackagePrivate && name.startsWith("access$") && (access & Opcodes.ACC_STATIC) != 0;
final boolean isBridge = (access & Opcodes.ACC_BRIDGE) != 0;
if (isAccessor || isBridge) {
return new MethodVisitor(this.api) {
@Override
public void visitMethodInsn(int opcode, String owner, String targetName, String targetDesc) {
if (selfclass.equals(owner)) {
if (isAccessor) {
actual2accessor.put(targetName + targetDesc, name + desc);
}
if (isBridge) {
bridge2specialization.put(name + desc, targetName + targetDesc);
}
}
}
};
}
}
// If this method is desugared lambda body
if ( isSynthetic && isPackagePrivate && name.startsWith("lambda$") ) {
// RetroLambda desugars method body to package private
desugaredLambdaBodies.add(name + desc);
return null;
}
return new MethodVisitor(this.api) {
private boolean methodContinuableAnnotationFound = false;
@Override
public AnnotationVisitor visitAnnotation(String description, boolean visible) {
if (!methodContinuableAnnotationFound) {
methodContinuableAnnotationFound = cciResolver.isContinuableAnnotation(description);
}
return null;
}
@Override
public void visitEnd() {
if (methodContinuableAnnotationFound) {
continuableMethods.add(name + desc);
}
}
};
}
@Before
public void generateClass() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, ClassNotFoundException, IOException {
Class.forName(JObfImpl.class.getCanonicalName());
InsnList methodInsns = new InsnList();
ClassNode classNode = new ClassNode();
classNode.name = "Test";
classNode.access = Opcodes.ACC_PUBLIC;
classNode.version = 52;
classNode.superName = "java/lang/Object";
MethodNode methodNode = new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "test", "()V", null, new String[0]);
for (int i1 = 0; i1 < 10; i1++) {
for (int i = 0; i <= 13; i++) {
LabelNode end = new LabelNode(new Label());
methodInsns.add(FlowObfuscator.generateIfGoto(i, end));
methodInsns.add(new TypeInsnNode(Opcodes.NEW, "java/lang/RuntimeException"));
methodInsns.add(new InsnNode(Opcodes.DUP));
methodInsns.add(new LdcInsnNode("JumpGenerator row=" + i1 + " id=" + i + " failed"));
methodInsns.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/String;)V", false));
methodInsns.add(new InsnNode(Opcodes.ATHROW));
methodInsns.add(end);
// methodInsns.add(new FrameNode(Opcodes.F_SAME, 0, null, 0, null));
}
}
methodInsns.add(new InsnNode(Opcodes.RETURN));
methodNode.instructions = methodInsns;
methodNode.visitEnd();
classNode.methods.add(methodNode);
ModifiedClassWriter writer = new ModifiedClassWriter(ModifiedClassWriter.COMPUTE_FRAMES);
classNode.accept(writer);
writer.visitEnd();
byte[] bytes = writer.toByteArray();
Files.write(bytes, File.createTempFile("JumpTestClass", ".class"));
Class<?> classLoaderClass = ClassLoader.class;
Method defineClass = classLoaderClass.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
defineClass.setAccessible(true);
generatedClass = (Class) defineClass.invoke(getClass().getClassLoader(), bytes, 0, bytes.length);
}
@Override
public boolean transform() throws Throwable {
decryptionClasses = new HideAccessClassFinder().findNames(classes.values());
logger.info("Detected the following hide access decryption classes: {}", decryptionClasses);
vm = TransformerHelper.newVirtualMachine(this);
prepareVM();
JavaClass reflectField = JavaClass.forName(vm, "java/lang/reflect/Field");
int decrypted = 0;
for (ClassNode classNode : classes.values()) {
for (MethodNode methodNode : new ArrayList<>(classNode.methods)) {
InstructionModifier modifier = new InstructionModifier();
for (AbstractInsnNode insn : TransformerHelper.instructionIterator(methodNode)) {
InstructionMatcher matcher = Helper.findMatch(insn,
HIDE_ACCESS_GETFIELD,
HIDE_ACCESS_GETSTATIC,
HIDE_ACCESS_PUTFIELD,
HIDE_ACCESS_PUTSTATIC,
HIDE_ACCESS_INVOKEVIRTUAL,
HIDE_ACCESS_INVOKESTATIC_INVOKESPECIAL
);
if (matcher == null) {
continue;
}
InsnList instructions = Constants.HIDE_ACCESS_HANDLERS.get(matcher.getPattern()).apply(this, matcher);
if (instructions == null) {
continue;
}
MethodNode decryptorMethod = new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, methodNode.name, "()V", null, null);
decryptorMethod.instructions.add(instructions);
captured.set(null);
classNode.methods.add(decryptorMethod);
vm.execute(classNode, decryptorMethod, null, Collections.<JavaWrapper>emptyList());
classNode.methods.remove(decryptorMethod);
if (captured.get() == null) {
throw new WrongTransformerException("Expected non-null java/lang/reflect/*");
}
logger.debug("Decrypted {} in {} {}{}", captured.get().asObject().javaToString(), classNode.name, methodNode.name, methodNode.desc);
modifier.removeAll(matcher.getCapturedInstructions("all"));
JavaWrapper classObj = captured.get().asObject().getField("clazz", "Ljava/lang/Class;");
ClassNode reflClass = java_lang_Class.getJavaClass(classObj).getClassNode();
if (captured.get().getJavaClass() == reflectField) {
FieldNode reflField = reflClass.fields.get(captured.get().asObject().getField("slot", "I").asInt());
int opcode;
if (Modifier.isStatic(reflField.access)) {
opcode = matcher.getPattern() == HIDE_ACCESS_GETSTATIC ? GETSTATIC : PUTSTATIC;
} else {
opcode = matcher.getPattern() == HIDE_ACCESS_GETFIELD ? GETFIELD : PUTFIELD;
}
InsnList replace = new InsnList();
if (opcode == PUTSTATIC || opcode == PUTFIELD) {
replace.add(TransformerHelper.unbox(Type.getType(reflField.desc)));
}
replace.add(new FieldInsnNode(opcode, reflClass.name, reflField.name, reflField.desc));
if (opcode == GETSTATIC || opcode == GETFIELD) {
replace.add(TransformerHelper.box(Type.getType(reflField.desc)));
}
modifier.replace(matcher.getEnd(), replace);
} else {
modifier.replace(matcher.getEnd(), convertMethodInvocation(methodNode, matcher.getCapturedInstruction("call"), captured.get()));
}
decrypted++;
}
modifier.apply(methodNode);
}
}
vm.shutdown();
logger.info("Decrypted {} hide access instruction", decrypted);
return true;
}
public boolean isPublic()
{
return (accessFlags & Opcodes.ACC_PUBLIC) != 0;
}
private void generateModelBridge(MethodInfo method, AnnotationValue targetReturnTypeErased) {
String descriptor = AsmUtil.getDescriptor(method, name -> typeArguments.get(name));
// JpaOperations erases the Id type to Object
String descriptorForJpaOperations = AsmUtil.getDescriptor(method,
name -> name.equals("Entity") ? entitySignature : null);
String signature = AsmUtil.getSignature(method, name -> typeArguments.get(name));
List<org.jboss.jandex.Type> parameters = method.parameters();
String castTo = null;
if (targetReturnTypeErased != null && targetReturnTypeErased.asBoolean()) {
org.jboss.jandex.Type type = method.returnType();
if (type.kind() == Kind.TYPE_VARIABLE &&
type.asTypeVariable().identifier().equals("Entity")) {
castTo = entityBinaryType;
}
if (castTo == null)
castTo = type.name().toString('/');
}
// Note: we can't use SYNTHETIC here because otherwise Mockito will never mock these methods
MethodVisitor mv = super.visitMethod(Opcodes.ACC_PUBLIC,
method.name(),
descriptor,
signature,
null);
for (int i = 0; i < parameters.size(); i++) {
mv.visitParameter(method.parameterName(i), 0 /* modifiers */);
}
mv.visitCode();
injectModel(mv);
for (int i = 0; i < parameters.size(); i++) {
mv.visitIntInsn(Opcodes.ALOAD, i + 1);
}
// inject Class
String forwardingDescriptor = "(" + getModelDescriptor() + descriptorForJpaOperations.substring(1);
if (castTo != null) {
// return type is erased to Object
int lastParen = forwardingDescriptor.lastIndexOf(')');
forwardingDescriptor = forwardingDescriptor.substring(0, lastParen + 1) + "Ljava/lang/Object;";
}
mv.visitMethodInsn(Opcodes.INVOKESTATIC,
getPanacheOperationsBinaryName(),
method.name(),
forwardingDescriptor, false);
if (castTo != null)
mv.visitTypeInsn(Opcodes.CHECKCAST, castTo);
String returnTypeDescriptor = descriptor.substring(descriptor.lastIndexOf(")") + 1);
mv.visitInsn(AsmUtil.getReturnInstruction(returnTypeDescriptor));
mv.visitMaxs(0, 0);
mv.visitEnd();
}
@Override
public void checkClass(@NonNull ClassContext context, @NonNull ClassNode classNode) {
if (!mHaveClasses && !context.isFromClassLibrary()
&& context.getProject() == context.getMainProject()) {
mHaveClasses = true;
}
String curr = classNode.name;
if (mReferencedClasses != null && mReferencedClasses.containsKey(curr)) {
boolean isCustomView = mCustomViews.contains(curr);
removeReferences(curr);
// Ensure that the class is public, non static and has a null constructor!
if ((classNode.access & Opcodes.ACC_PUBLIC) == 0) {
context.report(INSTANTIATABLE, context.getLocation(classNode), String.format(
"This class should be public (%1$s)",
ClassContext.createSignature(classNode.name, null, null)));
return;
}
if (classNode.name.indexOf('$') != -1 && !LintUtils.isStaticInnerClass(classNode)) {
context.report(INSTANTIATABLE, context.getLocation(classNode), String.format(
"This inner class should be static (%1$s)",
ClassContext.createSignature(classNode.name, null, null)));
return;
}
boolean hasDefaultConstructor = false;
@SuppressWarnings("rawtypes") // ASM API
List methodList = classNode.methods;
for (Object m : methodList) {
MethodNode method = (MethodNode) m;
if (method.name.equals(CONSTRUCTOR_NAME)) {
if (method.desc.equals("()V")) { //$NON-NLS-1$
// The constructor must be public
if ((method.access & Opcodes.ACC_PUBLIC) != 0) {
hasDefaultConstructor = true;
} else {
context.report(INSTANTIATABLE, context.getLocation(method, classNode),
"The default constructor must be public");
// Also mark that we have a constructor so we don't complain again
// below since we've already emitted a more specific error related
// to the default constructor
hasDefaultConstructor = true;
}
}
}
}
if (!hasDefaultConstructor && !isCustomView && !context.isFromClassLibrary()
&& context.getProject().getReportIssues()) {
context.report(INSTANTIATABLE, context.getLocation(classNode), String.format(
"This class should provide a default constructor (a public " +
"constructor with no arguments) (%1$s)",
ClassContext.createSignature(classNode.name, null, null)));
}
}
}
/**
* If a method/field is not private, make it public. This is to workaround the fact
* <ul>Our restart.dex files are loaded with a different class loader than the main dex file
* class loader on restart. so we need methods/fields to be public</ul>
* <ul>Our reload.dex are loaded from a different class loader as well but methods/fields
* are accessed through reflection, yet you need class visibility.</ul>
* <p>
* remember that in Java, protected methods or fields can be acessed by classes in the same
* package :
* {@see https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html}
*
* @param access the original class/method/field access.
* @return the new access or the same one depending on the original access rights.
*/
private static int transformAccessForInstantRun(int access) {
AccessRight accessRight = AccessRight.fromNodeAccess(access);
if (accessRight != AccessRight.PRIVATE) {
access &= ~Opcodes.ACC_PROTECTED;
access &= ~Opcodes.ACC_PRIVATE;
return access | Opcodes.ACC_PUBLIC;
}
return access;
}
/**
* Creates a ClassNode using a given class.
* Unlike make(String) this method will not use the cache
* to create the ClassNode. This means the ClassNode created
* from this method using the same name will have a different
* reference
*
* @param name of the class the ClassNode is representing
* @see #make(String)
*/
public static ClassNode makeWithoutCaching(String name) {
ClassNode cn = new ClassNode(name, Opcodes.ACC_PUBLIC, OBJECT_TYPE);
cn.isPrimaryNode = false;
return cn;
}
/**
* If a class is package private, make it public so instrumented code living in a different
* class loader can instantiate them.
*
* @param access the original class/method/field access.
* @return the new access or the same one depending on the original access rights.
*/
private static int transformClassAccessForInstantRun(int access) {
AccessRight accessRight = AccessRight.fromNodeAccess(access);
return accessRight == AccessRight.PACKAGE_PRIVATE ? access | Opcodes.ACC_PUBLIC : access;
}