// not used anymore. private void notTestGetInner() throws Exception { ClassPool pool = ClassPool.getDefault(); CtClass c = pool.get("javassist.CtMethod.ConstParameter"); CtClass d = pool.get("javassist.CtMethod.ConstParameter"); CtClass e = pool.get("javassist.CtMethod$ConstParameter"); assertSame(c, d); assertSame(c, e); try { c = pool.get("test2.Inner.Fake"); fail("found not-existing class"); } catch (NotFoundException ex) { } }
public void not_testURLClassPath() throws Exception { String host = "www.csg.is.titech.ac.jp"; String path = "/~chiba/tmp/"; String url; ClassPool cp = new ClassPool(null); cp.insertClassPath(new URLClassPath(host, 80, path, "test")); url = cp.find("test.TestClassPath").toString(); System.out.println(url); assertEquals("http://" + host + ":80" + path + "test/TestClassPath.class", url); assertNull(cp.find("test.No")); }
public void testInheritance() throws Exception { ClassPool pool = ClassPool.getDefault(); String classname = "test2.Inherit"; CtClass target = pool.get(classname); String src = "public void sampleMethod() {" + " test2.Inherit i = new test2.Inherit();" + " test2.Inherit2 i2 = i;" + " test2.Inherit3 i3 = i;" + " i3.foo2(); i3.foo2(); i2.foo1(); }"; CtMethod newmethod = CtNewMethod.make(src, target); target.addMethod(newmethod); target.writeFile(); }
/** * Writes the given word to the given writer, after having adapted it, based on the renamed class * names. */ private void writeUpdatedWord(Writer writer, String word) throws IOException { if (word.length() > 0) { String newWord = word; boolean containsDots = word.indexOf('.') >= 0; // Replace dots by forward slashes. String className = containsDots ? word.replace('.', ClassConstants.INTERNAL_PACKAGE_SEPARATOR) : word; // Find the class corrsponding to the word. Clazz clazz = classPool.getClass(className); if (clazz != null) { // Update the word if necessary. String newClassName = clazz.getName(); if (!className.equals(newClassName)) { // Replace forward slashes by dots. newWord = containsDots ? newClassName.replace(ClassConstants.INTERNAL_PACKAGE_SEPARATOR, '.') : newClassName; } } writer.write(newWord); } }
public void testInner() throws Exception { ClassPool pool = ClassPool.getDefault(); String classname = "test2.Inner"; CtClass target = pool.get(classname); String src = "public void sampleMethod() throws Exception {" + "java.util.Properties props = new java.util.Properties();" + "java.rmi.activation.ActivationGroupDesc.CommandEnvironment ace " + " = null;" + "java.rmi.activation.ActivationGroupDesc agd " + " = new java.rmi.activation.ActivationGroupDesc(props,ace);}"; CtMethod newmethod = CtNewMethod.make(src, target); target.addMethod(newmethod); String src2 = "public java.lang.Character.Subset sampleMethod2() {" + " java.lang.Character.Subset s " + " = Character.UnicodeBlock.HIRAGANA; " + " return s; }"; CtMethod newmethod2 = CtNewMethod.make(src2, target); target.addMethod(newmethod2); target.writeFile(); }
/** * Finds the specified class using <code>ClassPath</code>. If the source throws an exception, this * returns null. * * <p>This method can be overridden by a subclass of <code>Loader</code>. Note that the overridden * method must not throw an exception when it just fails to find a class file. * * @return null if the specified class could not be found. * @throws ClassNotFoundException if an exception is thrown while obtaining a class file. */ protected Class findClass(String name) throws ClassNotFoundException { byte[] classfile; try { if (source != null) { if (translator != null) translator.onLoad(source, name); try { classfile = source.get(name).toBytecode(); } catch (NotFoundException e) { return null; } } else { String jarname = "/" + name.replace('.', '/') + ".class"; InputStream in = this.getClass().getResourceAsStream(jarname); if (in == null) return null; classfile = ClassPoolTail.readStream(in); } } catch (Exception e) { throw new ClassNotFoundException( "caught an exception while obtaining a class file for " + name, e); } int i = name.lastIndexOf('.'); if (i != -1) { String pname = name.substring(0, i); if (getPackage(pname) == null) try { definePackage(pname, null, null, null, null, null, null, null); } catch (IllegalArgumentException e) { // ignore. maybe the package object for the same // name has been created just right away. } } if (domain == null) return defineClass(name, classfile, 0, classfile.length); else return defineClass(name, classfile, 0, classfile.length, domain); }
/** Performs obfuscation of the given program class pool. */ public void execute(ClassPool programClassPool, ClassPool libraryClassPool) throws IOException { // Check if we have at least some keep commands. if (configuration.keep == null && configuration.applyMapping == null && configuration.printMapping == null) { throw new IOException("You have to specify '-keep' options for the obfuscation step."); } // Clean up any old visitor info. programClassPool.classesAccept(new ClassCleaner()); libraryClassPool.classesAccept(new ClassCleaner()); // If the class member names have to correspond globally, // link all class members in all classes, otherwise // link all non-private methods in all class hierarchies. ClassVisitor memberInfoLinker = configuration.useUniqueClassMemberNames ? (ClassVisitor) new AllMemberVisitor(new MethodLinker()) : (ClassVisitor) new BottomClassFilter(new MethodLinker()); programClassPool.classesAccept(memberInfoLinker); libraryClassPool.classesAccept(memberInfoLinker); // Create a visitor for marking the seeds. NameMarker nameMarker = new NameMarker(); ClassPoolVisitor classPoolvisitor = ClassSpecificationVisitorFactory.createClassPoolVisitor( configuration.keep, nameMarker, nameMarker, false, false, true); // Mark the seeds. programClassPool.accept(classPoolvisitor); libraryClassPool.accept(classPoolvisitor); // All library classes and library class members keep their names. libraryClassPool.classesAccept(nameMarker); libraryClassPool.classesAccept(new AllMemberVisitor(nameMarker)); // Mark attributes that have to be kept. AttributeUsageMarker requiredAttributeUsageMarker = new AttributeUsageMarker(); AttributeVisitor optionalAttributeUsageMarker = configuration.keepAttributes == null ? null : new AttributeNameFilter( new ListParser(new NameParser()).parse(configuration.keepAttributes), requiredAttributeUsageMarker); programClassPool.classesAccept( new AllAttributeVisitor( true, new RequiredAttributeFilter( requiredAttributeUsageMarker, optionalAttributeUsageMarker))); // Remove the attributes that can be discarded. Note that the attributes // may only be discarded after the seeds have been marked, since the // configuration may rely on annotations. programClassPool.classesAccept(new AttributeShrinker()); // Apply the mapping, if one has been specified. The mapping can // override the names of library classes and of library class members. if (configuration.applyMapping != null) { WarningPrinter warningPrinter = new WarningPrinter(System.err, configuration.warn); MappingReader reader = new MappingReader(configuration.applyMapping); MappingProcessor keeper = new MultiMappingProcessor( new MappingProcessor[] { new MappingKeeper(programClassPool, warningPrinter), new MappingKeeper(libraryClassPool, null), }); reader.pump(keeper); // Print out a summary of the warnings if necessary. int mappingWarningCount = warningPrinter.getWarningCount(); if (mappingWarningCount > 0) { System.err.println( "Warning: there were " + mappingWarningCount + " kept classes and class members that were remapped anyway."); System.err.println( " You should adapt your configuration or edit the mapping file."); if (!configuration.ignoreWarnings) { System.err.println(" If you are sure this remapping won't hurt,"); System.err.println( " you could try your luck using the '-ignorewarnings' option."); throw new IOException("Please correct the above warnings first."); } } } // Come up with new names for all classes. DictionaryNameFactory classNameFactory = configuration.classObfuscationDictionary != null ? new DictionaryNameFactory(configuration.classObfuscationDictionary, null) : null; DictionaryNameFactory packageNameFactory = configuration.packageObfuscationDictionary != null ? new DictionaryNameFactory(configuration.packageObfuscationDictionary, null) : null; programClassPool.classesAccept( new ClassObfuscator( programClassPool, classNameFactory, packageNameFactory, configuration.useMixedCaseClassNames, configuration.keepPackageNames, configuration.flattenPackageHierarchy, configuration.repackageClasses, configuration.allowAccessModification)); // Come up with new names for all class members. NameFactory nameFactory = new SimpleNameFactory(); if (configuration.obfuscationDictionary != null) { nameFactory = new DictionaryNameFactory(configuration.obfuscationDictionary, nameFactory); } WarningPrinter warningPrinter = new WarningPrinter(System.err, configuration.warn); // Maintain a map of names to avoid [descriptor - new name - old name]. Map descriptorMap = new HashMap(); // Do the class member names have to be globally unique? if (configuration.useUniqueClassMemberNames) { // Collect all member names in all classes. programClassPool.classesAccept( new AllMemberVisitor( new MemberNameCollector(configuration.overloadAggressively, descriptorMap))); // Assign new names to all members in all classes. programClassPool.classesAccept( new AllMemberVisitor( new MemberObfuscator( configuration.overloadAggressively, nameFactory, descriptorMap))); } else { // Come up with new names for all non-private class members. programClassPool.classesAccept( new MultiClassVisitor( new ClassVisitor[] { // Collect all private member names in this class and down // the hierarchy. new ClassHierarchyTraveler( true, false, false, true, new AllMemberVisitor( new MemberAccessFilter( ClassConstants.INTERNAL_ACC_PRIVATE, 0, new MemberNameCollector( configuration.overloadAggressively, descriptorMap)))), // Collect all non-private member names anywhere in the hierarchy. new ClassHierarchyTraveler( true, true, true, true, new AllMemberVisitor( new MemberAccessFilter( 0, ClassConstants.INTERNAL_ACC_PRIVATE, new MemberNameCollector( configuration.overloadAggressively, descriptorMap)))), // Assign new names to all non-private members in this class. new AllMemberVisitor( new MemberAccessFilter( 0, ClassConstants.INTERNAL_ACC_PRIVATE, new MemberObfuscator( configuration.overloadAggressively, nameFactory, descriptorMap))), // Clear the collected names. new MapCleaner(descriptorMap) })); // Come up with new names for all private class members. programClassPool.classesAccept( new MultiClassVisitor( new ClassVisitor[] { // Collect all member names in this class. new AllMemberVisitor( new MemberNameCollector(configuration.overloadAggressively, descriptorMap)), // Collect all non-private member names higher up the hierarchy. new ClassHierarchyTraveler( false, true, true, false, new AllMemberVisitor( new MemberAccessFilter( 0, ClassConstants.INTERNAL_ACC_PRIVATE, new MemberNameCollector( configuration.overloadAggressively, descriptorMap)))), // Assign new names to all private members in this class. new AllMemberVisitor( new MemberAccessFilter( ClassConstants.INTERNAL_ACC_PRIVATE, 0, new MemberObfuscator( configuration.overloadAggressively, nameFactory, descriptorMap))), // Clear the collected names. new MapCleaner(descriptorMap) })); } // Some class members may have ended up with conflicting names. // Come up with new, globally unique names for them. NameFactory specialNameFactory = new SpecialNameFactory(new SimpleNameFactory()); // Collect a map of special names to avoid // [descriptor - new name - old name]. Map specialDescriptorMap = new HashMap(); programClassPool.classesAccept( new AllMemberVisitor( new MemberSpecialNameFilter( new MemberNameCollector( configuration.overloadAggressively, specialDescriptorMap)))); libraryClassPool.classesAccept( new AllMemberVisitor( new MemberSpecialNameFilter( new MemberNameCollector( configuration.overloadAggressively, specialDescriptorMap)))); // Replace conflicting non-private member names with special names. programClassPool.classesAccept( new MultiClassVisitor( new ClassVisitor[] { // Collect all private member names in this class and down // the hierarchy. new ClassHierarchyTraveler( true, false, false, true, new AllMemberVisitor( new MemberAccessFilter( ClassConstants.INTERNAL_ACC_PRIVATE, 0, new MemberNameCollector( configuration.overloadAggressively, descriptorMap)))), // Collect all non-private member names in this class and // higher up the hierarchy. new ClassHierarchyTraveler( true, true, true, false, new AllMemberVisitor( new MemberAccessFilter( 0, ClassConstants.INTERNAL_ACC_PRIVATE, new MemberNameCollector( configuration.overloadAggressively, descriptorMap)))), // Assign new names to all conflicting non-private members // in this class and higher up the hierarchy. new ClassHierarchyTraveler( true, true, true, false, new AllMemberVisitor( new MemberAccessFilter( 0, ClassConstants.INTERNAL_ACC_PRIVATE, new MemberNameConflictFixer( configuration.overloadAggressively, descriptorMap, warningPrinter, new MemberObfuscator( configuration.overloadAggressively, specialNameFactory, specialDescriptorMap))))), // Clear the collected names. new MapCleaner(descriptorMap) })); // Replace conflicting private member names with special names. // This is only possible if those names were kept or mapped. programClassPool.classesAccept( new MultiClassVisitor( new ClassVisitor[] { // Collect all member names in this class. new AllMemberVisitor( new MemberNameCollector(configuration.overloadAggressively, descriptorMap)), // Collect all non-private member names higher up the hierarchy. new ClassHierarchyTraveler( false, true, true, false, new AllMemberVisitor( new MemberAccessFilter( 0, ClassConstants.INTERNAL_ACC_PRIVATE, new MemberNameCollector( configuration.overloadAggressively, descriptorMap)))), // Assign new names to all conflicting private members in this // class. new AllMemberVisitor( new MemberAccessFilter( ClassConstants.INTERNAL_ACC_PRIVATE, 0, new MemberNameConflictFixer( configuration.overloadAggressively, descriptorMap, warningPrinter, new MemberObfuscator( configuration.overloadAggressively, specialNameFactory, specialDescriptorMap)))), // Clear the collected names. new MapCleaner(descriptorMap) })); // Print out any warnings about member name conflicts. int warningCount = warningPrinter.getWarningCount(); if (warningCount > 0) { System.err.println( "Warning: there were " + warningCount + " conflicting class member name mappings."); System.err.println(" Your configuration may be inconsistent."); if (!configuration.ignoreWarnings) { System.err.println(" If you are sure the conflicts are harmless,"); System.err.println(" you could try your luck using the '-ignorewarnings' option."); throw new IOException("Please correct the above warnings first."); } } // Print out the mapping, if requested. if (configuration.printMapping != null) { PrintStream ps = isFile(configuration.printMapping) ? new PrintStream( new BufferedOutputStream(new FileOutputStream(configuration.printMapping))) : System.out; // Print out items that will be removed. programClassPool.classesAcceptAlphabetically(new MappingPrinter(ps)); if (ps != System.out) { ps.close(); } } // Actually apply the new names. programClassPool.classesAccept(new ClassRenamer()); libraryClassPool.classesAccept(new ClassRenamer()); // Update all references to these new names. programClassPool.classesAccept(new ClassReferenceFixer(false)); libraryClassPool.classesAccept(new ClassReferenceFixer(false)); programClassPool.classesAccept(new MemberReferenceFixer()); // Make package visible elements public or protected, if obfuscated // classes are being repackaged aggressively. if (configuration.repackageClasses != null && configuration.allowAccessModification) { programClassPool.classesAccept(new AllConstantVisitor(new AccessFixer())); } // Rename the source file attributes, if requested. if (configuration.newSourceFileAttribute != null) { programClassPool.classesAccept(new SourceFileRenamer(configuration.newSourceFileAttribute)); } // Mark NameAndType constant pool entries that have to be kept // and remove the other ones. programClassPool.classesAccept(new NameAndTypeUsageMarker()); programClassPool.classesAccept(new NameAndTypeShrinker()); // Mark Utf8 constant pool entries that have to be kept // and remove the other ones. programClassPool.classesAccept(new Utf8UsageMarker()); programClassPool.classesAccept(new Utf8Shrinker()); }
public void testToClass() throws Exception { ClassPool cp = ClassPool.getDefault(); CtClass cc = cp.makeClass("test2.ToClassTest"); Class c = cc.toClass(); assertEquals(getClass().getClassLoader(), c.getClassLoader()); }
public void testURL() throws Exception { String url; ClassPool cp = new ClassPool(null); cp.appendSystemPath(); url = cp.find("java.lang.Object").toString(); System.out.println(url); assertTrue(url.startsWith("jar:file:")); assertTrue(url.endsWith(".jar!/java/lang/Object.class")); assertNull(cp.find("class.not.Exist")); cp = new ClassPool(null); cp.insertClassPath("."); url = cp.find("test2.Inner").toString(); System.out.println(url); assertTrue(url.startsWith("file:/")); assertTrue(url.endsWith("/test2/Inner.class")); assertNull(cp.find("test2.TestURL")); cp = new ClassPool(null); cp.insertClassPath(JAR_PATH + "javassist.jar"); url = cp.find("javassist.CtClass").toString(); System.out.println(url); assertTrue(url.startsWith("jar:file:")); assertTrue(url.endsWith("javassist.jar!/javassist/CtClass.class")); assertNull(cp.find("javassist.TestURL")); cp = new ClassPool(null); cp.insertClassPath(new LoaderClassPath(cloader)); url = cp.find("javassist.CtMethod").toString(); System.out.println(url); // assertTrue(url.startsWith("jar:file:")); // assertTrue(url.endsWith("javassist.jar!/javassist/CtMethod.class")); assertNull(cp.find("javassist.TestURL")); cp = new ClassPool(null); cp.insertClassPath(new ByteArrayClassPath("test2.ByteArray", null)); url = cp.find("test2.ByteArray").toString(); System.out.println(url); assertTrue(url.equals("file:/ByteArrayClassPath/test2/ByteArray.class")); assertNull(cp.find("test2.TestURL")); }
private void createClass(String classname) throws CannotCompileException, IOException { ClassPool pool = ClassPool.getDefault(); CtClass foobarClass = pool.makeClass(classname); foobarClass.writeFile(newDir.getAbsolutePath()); }