- 浏览: 888360 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
zzuliuli:
很实用,一直关注
mysql的执行计划 -
rxin2009:
你好,最近在解决redis数据同步的问题,找到了tedis,但 ...
taobao/tedis的redis集群 -
zhangping2056:
楼主接下来要考虑页面静态化与细节上面的东西了
Nginx与Redis解决高并发问题 -
XieFuQ:
Tomcat的重启shell脚本 -
jovinlee:
jovinlee 写道 jov ...
Tomcat的重启shell脚本
因服务框架需要用动态代理生成客户端接口的stub,所以做了一下性能评测,
动态代理工具比较成熟的产品有:
JDK自带的,ASM,CGLIB(基于ASM包装),JAVAASSIST,
使用的版本分别为:
JDK-1.6.0_18-b07, ASM-3.3, CGLIB-2.2, JAVAASSIST-3.11.0.GA
(一) 测试结果:
数据为执行三次,每次调用一千万次代理方法的结果,测试代码后面有贴出。
(1) PC机测试结果:Linux 2.6.9-42.ELsmp(32bit), 2 Cores CPU(Intel Pentium4 3.06GHz)
Create JDK Proxy: 13 ms
Create CGLIB Proxy: 217 ms
Create JAVAASSIST Proxy: 99 ms
Create JAVAASSIST Bytecode Proxy: 168 ms
Create ASM Proxy: 3 ms
================
Run JDK Proxy: 2224 ms, 634,022 t/s
Run CGLIB Proxy: 1123 ms, 1,255,623 t/s
Run JAVAASSIST Proxy: 3212 ms, 438,999 t/s
Run JAVAASSIST Bytecode Proxy: 206 ms, 6,844,977 t/s
Run ASM Bytecode Proxy: 209 ms, 6,746,724 t/s
—————-
Run JDK Proxy: 2169 ms, 650,099 t/s
Run CGLIB Proxy: 1059 ms, 1,331,506 t/s
Run JAVAASSIST Proxy: 3328 ms, 423,697 t/s
Run JAVAASSIST Bytecode Proxy: 202 ms, 6,980,521 t/s
Run ASM Bytecode Proxy: 206 ms, 6,844,977 t/s
—————-
Run JDK Proxy: 2174 ms, 648,604 t/s
Run CGLIB Proxy: 1032 ms, 1,366,342 t/s
Run JAVAASSIST Proxy: 3119 ms, 452,088 t/s
Run JAVAASSIST Bytecode Proxy: 207 ms, 6,811,910 t/s
Run ASM Bytecode Proxy: 207 ms, 6,811,910 t/s
—————-
(2) 服务器测试结果:Linux 2.6.18-128.el5xen(64bit), 16 Cores CPU(Intel Xeon E5520 2.27GHz)
Create JDK Proxy: 7 ms
Create CGLIB Proxy: 86 ms
Create JAVAASSIST Proxy: 36 ms
Create JAVAASSIST Bytecode Proxy: 57 ms
Create ASM Proxy: 1 ms
================
Run JDK Proxy: 235 ms, 6,000,278 t/s
Run CGLIB Proxy: 234 ms, 6,025,920 t/s
Run JAVAASSIST Proxy: 459 ms, 3,072,037 t/s
Run JAVAASSIST Bytecode Proxy: 71 ms, 19,860,076 t/s
Run ASM Bytecode Proxy: 72 ms, 19,584,241 t/s
—————-
Run JDK Proxy: 298 ms, 4,731,763 t/s
Run CGLIB Proxy: 134 ms, 10,522,876 t/s
Run JAVAASSIST Proxy: 406 ms, 3,473,067 t/s
Run JAVAASSIST Bytecode Proxy: 67 ms, 21,045,752 t/s
Run ASM Bytecode Proxy: 66 ms, 21,364,627 t/s
—————-
Run JDK Proxy: 282 ms, 5,000,231 t/s
Run CGLIB Proxy: 133 ms, 10,601,995 t/s
Run JAVAASSIST Proxy: 406 ms, 3,473,067 t/s
Run JAVAASSIST Bytecode Proxy: 67 ms, 21,045,752 t/s
Run ASM Bytecode Proxy: 67 ms, 21,045,752 t/s
—————-
(二) 测试结论:
1. ASM和JAVAASSIST字节码生成方式不相上下,都很快,是CGLIB的5倍。
2. CGLIB次之,是JDK自带的两倍。
3. JDK自带的再次之,因JDK1.6对动态代理做了优化,如果用低版本JDK更慢,要注意的是JDK也是通过字节码生成来实现动态代理的,而不是反射。
4. JAVAASSIST提供者动态代理接口最慢,比JDK自带的还慢。
(这也是为什么网上有人说JAVAASSIST比JDK还慢的原因,用JAVAASSIST最好别用它提供的动态代理接口,而可以考虑用它的字节码生成方式)
(三) 差异原因:
各方案生成的字节码不一样,
像JDK和CGLIB都考虑了很多因素,以及继承或包装了自己的一些类,
所以生成的字节码非常大,而我们很多时候用不上这些,
而手工生成的字节码非常小,所以速度快,
具体的字节码对比,后面有贴出,可自行分析。
(四) 最终选型:
最终决定使用JAVAASSIST的字节码生成代理方式,
虽然ASM稍快,但并没有快一个数量级,
而JAVAASSIST的字节码生成方式比ASM方便,
JAVAASSIST只需用字符串拼接出Java源码,便可生成相应字节码,
而ASM需要手工写字节码。
(五) 测试代码:
public interface CountService {
int count();
}
public class CountServiceImpl implements CountService {
private int count = 0;
public int count() {
return count ++;
}
}
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.text.DecimalFormat;import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtField;
import javassist.CtNewConstructor;
import javassist.CtNewMethod;
import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.ProxyFactory;
import javassist.util.proxy.ProxyObject;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;public class DynamicProxyPerformanceTest {
public static void main(String[] args) throws Exception {
CountService delegate = new CountServiceImpl();long time = System.currentTimeMillis();
CountService jdkProxy = createJdkDynamicProxy(delegate);
time = System.currentTimeMillis() – time;
System.out.println(“Create JDK Proxy: ” + time + ” ms”);time = System.currentTimeMillis();
CountService cglibProxy = createCglibDynamicProxy(delegate);
time = System.currentTimeMillis() – time;
System.out.println(“Create CGLIB Proxy: ” + time + ” ms”);time = System.currentTimeMillis();
CountService javassistProxy = createJavassistDynamicProxy(delegate);
time = System.currentTimeMillis() – time;
System.out.println(“Create JAVAASSIST Proxy: ” + time + ” ms”);time = System.currentTimeMillis();
CountService javassistBytecodeProxy = createJavassistBytecodeDynamicProxy(delegate);
time = System.currentTimeMillis() – time;
System.out.println(“Create JAVAASSIST Bytecode Proxy: ” + time + ” ms”);time = System.currentTimeMillis();
CountService asmBytecodeProxy = createAsmBytecodeDynamicProxy(delegate);
time = System.currentTimeMillis() – time;
System.out.println(“Create ASM Proxy: ” + time + ” ms”);
System.out.println(“================”);for (int i = 0; i < 3; i++) {
test(jdkProxy, “Run JDK Proxy: “);
test(cglibProxy, “Run CGLIB Proxy: “);
test(javassistProxy, “Run JAVAASSIST Proxy: “);
test(javassistBytecodeProxy, “Run JAVAASSIST Bytecode Proxy: “);
test(asmBytecodeProxy, “Run ASM Bytecode Proxy: “);
System.out.println(“—————-”);
}
}private static void test(CountService service, String label)
throws Exception {
service.count(); // warm up
int count = 10000000;
long time = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
service.count();
}
time = System.currentTimeMillis() – time;
System.out.println(label + time + ” ms, ” + new DecimalFormat().format(count * 1000 / time) + ” t/s”);
}private static CountService createJdkDynamicProxy(final CountService delegate) {
CountService jdkProxy = (CountService) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
new Class[] { CountService.class }, new JdkHandler(delegate));
return jdkProxy;
}private static class JdkHandler implements InvocationHandler {
final Object delegate;
JdkHandler(Object delegate) {
this.delegate = delegate;
}public Object invoke(Object object, Method method, Object[] objects)
throws Throwable {
return method.invoke(delegate, objects);
}
}private static CountService createCglibDynamicProxy(final CountService delegate) throws Exception {
Enhancer enhancer = new Enhancer();
enhancer.setCallback(new CglibInterceptor(delegate));
enhancer.setInterfaces(new Class[] { CountService.class });
CountService cglibProxy = (CountService) enhancer.create();
return cglibProxy;
}private static class CglibInterceptor implements MethodInterceptor {
final Object delegate;
CglibInterceptor(Object delegate) {
this.delegate = delegate;
}public Object intercept(Object object, Method method, Object[] objects,
MethodProxy methodProxy) throws Throwable {
return methodProxy.invoke(delegate, objects);
}
}private static CountService createJavassistDynamicProxy(final CountService delegate) throws Exception {
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setInterfaces(new Class[] { CountService.class });
Class<?> proxyClass = proxyFactory.createClass();
CountService javassistProxy = (CountService) proxyClass.newInstance();
((ProxyObject) javassistProxy).setHandler(new JavaAssitInterceptor(delegate));
return javassistProxy;
}private static class JavaAssitInterceptor implements MethodHandler {
final Object delegate;
JavaAssitInterceptor(Object delegate) {
this.delegate = delegate;
}public Object invoke(Object self, Method m, Method proceed,
Object[] args) throws Throwable {
return m.invoke(delegate, args);
}
}private static CountService createJavassistBytecodeDynamicProxy(CountService delegate) throws Exception {
ClassPool mPool = new ClassPool(true);
CtClass mCtc = mPool.makeClass(CountService.class.getName() + “JavaassistProxy”);
mCtc.addInterface(mPool.get(CountService.class.getName()));
mCtc.addConstructor(CtNewConstructor.defaultConstructor(mCtc));
mCtc.addField(CtField.make(“public ” + CountService.class.getName() + ” delegate;”, mCtc));
mCtc.addMethod(CtNewMethod.make(“public int count() { return delegate.count(); }”, mCtc));
Class<?> pc = mCtc.toClass();
CountService bytecodeProxy = (CountService) pc.newInstance();
Field filed = bytecodeProxy.getClass().getField(“delegate”);
filed.set(bytecodeProxy, delegate);
return bytecodeProxy;
}private static CountService createAsmBytecodeDynamicProxy(CountService delegate) throws Exception {
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
String className = CountService.class.getName() + “AsmProxy”;
String classPath = className.replace(‘.’, ‘/’);
String interfacePath = CountService.class.getName().replace(‘.’, ‘/’);
classWriter.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC, classPath, null, “java/lang/Object”, new String[] {interfacePath});MethodVisitor initVisitor = classWriter.visitMethod(Opcodes.ACC_PUBLIC, “<init>”, “()V”, null, null);
initVisitor.visitCode();
initVisitor.visitVarInsn(Opcodes.ALOAD, 0);
initVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, “java/lang/Object”, “<init>”, “()V”);
initVisitor.visitInsn(Opcodes.RETURN);
initVisitor.visitMaxs(0, 0);
initVisitor.visitEnd();FieldVisitor fieldVisitor = classWriter.visitField(Opcodes.ACC_PUBLIC, “delegate”, “L” + interfacePath + “;”, null, null);
fieldVisitor.visitEnd();MethodVisitor methodVisitor = classWriter.visitMethod(Opcodes.ACC_PUBLIC, “count”, “()I”, null, null);
methodVisitor.visitCode();
methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
methodVisitor.visitFieldInsn(Opcodes.GETFIELD, classPath, “delegate”, “L” + interfacePath + “;”);
methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, interfacePath, “count”, “()I”);
methodVisitor.visitInsn(Opcodes.IRETURN);
methodVisitor.visitMaxs(0, 0);
methodVisitor.visitEnd();classWriter.visitEnd();
byte[] code = classWriter.toByteArray();
CountService bytecodeProxy = (CountService) new ByteArrayClassLoader().getClass(className, code).newInstance();
Field filed = bytecodeProxy.getClass().getField(“delegate”);
filed.set(bytecodeProxy, delegate);
return bytecodeProxy;
}private static class ByteArrayClassLoader extends ClassLoader {
public ByteArrayClassLoader() {
super(ByteArrayClassLoader.class.getClassLoader());
}public synchronized Class<?> getClass(String name, byte[] code) {
if (name == null) {
throw new IllegalArgumentException(“”);
}
return defineClass(name, code, 0, code.length);
}}
}
(六) 字节码对比
(1) JDK生成的字节码:
public final class $Proxy0 extends java.lang.reflect.Proxy implements com.alibaba.test.performance.dynamicproxy.CountService{
public $Proxy0(java.lang.reflect.InvocationHandler) throws ;
Code:
0: aload_0
1: aload_1
2: invokespecial #8; //Method java/lang/reflect/Proxy.”":(Ljava/lang/reflect/InvocationHandler;)V
5: returnpublic final boolean equals(java.lang.Object) throws ;
Code:
0: aload_0
1: getfield #16; //Field java/lang/reflect/Proxy.h:Ljava/lang/reflect/InvocationHandler;
4: aload_0
5: getstatic #20; //Field m1:Ljava/lang/reflect/Method;
8: iconst_1
9: anewarray #22; //class java/lang/Object
12: dup
13: iconst_0
14: aload_1
15: aastore
16: invokeinterface #28, 4; //InterfaceMethod java/lang/reflect/InvocationHandler.invoke:(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
21: checkcast #30; //class java/lang/Boolean
24: invokevirtual #34; //Method java/lang/Boolean.booleanValue:()Z
27: ireturn
28: athrow
29: astore_2
30: new #42; //class java/lang/reflect/UndeclaredThrowableException
33: dup
34: aload_2
35: invokespecial #45; //Method java/lang/reflect/UndeclaredThrowableException."":(Ljava/lang/Throwable;)V
38: athrow
Exception table:
from to target type
0 28 28 Class java/lang/Error0 28 28 Class java/lang/RuntimeException
0 28 29 Class java/lang/Throwable
public final int count() throws ;
Code:
0: aload_0
1: getfield #16; //Field java/lang/reflect/Proxy.h:Ljava/lang/reflect/InvocationHandler;
4: aload_0
5: getstatic #50; //Field m3:Ljava/lang/reflect/Method;
8: aconst_null
9: invokeinterface #28, 4; //InterfaceMethod java/lang/reflect/InvocationHandler.invoke:(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
14: checkcast #52; //class java/lang/Integer
17: invokevirtual #55; //Method java/lang/Integer.intValue:()I
20: ireturn
21: athrow
22: astore_1
23: new #42; //class java/lang/reflect/UndeclaredThrowableException
26: dup
27: aload_1
28: invokespecial #45; //Method java/lang/reflect/UndeclaredThrowableException."":(Ljava/lang/Throwable;)V
31: athrow
Exception table:
from to target type
0 21 21 Class java/lang/Error0 21 21 Class java/lang/RuntimeException
0 21 22 Class java/lang/Throwable
public final int hashCode() throws ;
Code:
0: aload_0
1: getfield #16; //Field java/lang/reflect/Proxy.h:Ljava/lang/reflect/InvocationHandler;
4: aload_0
5: getstatic #59; //Field m0:Ljava/lang/reflect/Method;
8: aconst_null
9: invokeinterface #28, 4; //InterfaceMethod java/lang/reflect/InvocationHandler.invoke:(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
14: checkcast #52; //class java/lang/Integer
17: invokevirtual #55; //Method java/lang/Integer.intValue:()I
20: ireturn
21: athrow
22: astore_1
23: new #42; //class java/lang/reflect/UndeclaredThrowableException
26: dup
27: aload_1
28: invokespecial #45; //Method java/lang/reflect/UndeclaredThrowableException."":(Ljava/lang/Throwable;)V
31: athrow
Exception table:
from to target type
0 21 21 Class java/lang/Error0 21 21 Class java/lang/RuntimeException
0 21 22 Class java/lang/Throwable
public final java.lang.String toString() throws ;
Code:
0: aload_0
1: getfield #16; //Field java/lang/reflect/Proxy.h:Ljava/lang/reflect/InvocationHandler;
4: aload_0
5: getstatic #64; //Field m2:Ljava/lang/reflect/Method;
8: aconst_null
9: invokeinterface #28, 4; //InterfaceMethod java/lang/reflect/InvocationHandler.invoke:(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
14: checkcast #66; //class java/lang/String
17: areturn
18: athrow
19: astore_1
20: new #42; //class java/lang/reflect/UndeclaredThrowableException
23: dup
24: aload_1
25: invokespecial #45; //Method java/lang/reflect/UndeclaredThrowableException."":(Ljava/lang/Throwable;)V
28: athrow
Exception table:
from to target type
0 18 18 Class java/lang/Error0 18 18 Class java/lang/RuntimeException
0 18 19 Class java/lang/Throwable
static {} throws ;
Code:
0: ldc #70; //String java.lang.Object
2: invokestatic #76; //Method java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
5: ldc #77; //String equals
7: iconst_1
8: anewarray #72; //class java/lang/Class
11: dup
12: iconst_0
13: ldc #70; //String java.lang.Object
15: invokestatic #76; //Method java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
18: aastore
19: invokevirtual #81; //Method java/lang/Class.getMethod:(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
22: putstatic #20; //Field m1:Ljava/lang/reflect/Method;
25: ldc #83; //String com.alibaba.test.performance.dynamicproxy.CountService
27: invokestatic #76; //Method java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
30: ldc #84; //String count
32: iconst_0
33: anewarray #72; //class java/lang/Class
36: invokevirtual #81; //Method java/lang/Class.getMethod:(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
39: putstatic #50; //Field m3:Ljava/lang/reflect/Method;
42: ldc #70; //String java.lang.Object
44: invokestatic #76; //Method java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
47: ldc #85; //String hashCode
49: iconst_0
50: anewarray #72; //class java/lang/Class
53: invokevirtual #81; //Method java/lang/Class.getMethod:(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
56: putstatic #59; //Field m0:Ljava/lang/reflect/Method;
59: ldc #70; //String java.lang.Object
61: invokestatic #76; //Method java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
64: ldc #86; //String toString
66: iconst_0
67: anewarray #72; //class java/lang/Class
70: invokevirtual #81; //Method java/lang/Class.getMethod:(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
73: putstatic #64; //Field m2:Ljava/lang/reflect/Method;
76: return
77: astore_1
78: new #90; //class java/lang/NoSuchMethodError
81: dup
82: aload_1
83: invokevirtual #93; //Method java/lang/Throwable.getMessage:()Ljava/lang/String;
86: invokespecial #96; //Method java/lang/NoSuchMethodError."":(Ljava/lang/String;)V
89: athrow
90: astore_1
91: new #100; //class java/lang/NoClassDefFoundError
94: dup
95: aload_1
96: invokevirtual #93; //Method java/lang/Throwable.getMessage:()Ljava/lang/String;
99: invokespecial #101; //Method java/lang/NoClassDefFoundError."":(Ljava/lang/String;)V
102: athrow
Exception table:
from to target type
0 77 77 Class java/lang/NoSuchMethodException0 77 90 Class java/lang/ClassNotFoundException
}
(2) CGLIB生成的字节码:
public class net.sf.cglib.core.MethodWrapper$MethodWrapperKey$$KeyFactoryByCGLIB$$d45e49f7 extends net.sf.cglib.core.KeyFactory implements net.sf.cglib.core.MethodWrapper$MethodWrapperKey{
public net.sf.cglib.core.MethodWrapper$MethodWrapperKey$$KeyFactoryByCGLIB$$d45e49f7();
Code:
0: aload_0
1: invokespecial #11; //Method net/sf/cglib/core/KeyFactory."":()V
4: returnpublic java.lang.Object newInstance(java.lang.String, java.lang.String[], java.lang.String);
Code:
0: new #2; //class net/sf/cglib/core/MethodWrapper$MethodWrapperKey$$KeyFactoryByCGLIB$$d45e49f7
3: dup
4: aload_1
5: aload_2
6: aload_3
7: invokespecial #16; //Method “”:(Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)V
10: areturnpublic net.sf.cglib.core.MethodWrapper$MethodWrapperKey$$KeyFactoryByCGLIB$$d45e49f7(java.lang.String, java.lang.String[], java.lang.String);
Code:
0: aload_0
1: invokespecial #11; //Method net/sf/cglib/core/KeyFactory.”":()V
4: aload_0
5: dup
6: aload_1
7: putfield #20; //Field FIELD_0:Ljava/lang/String;
10: dup
11: aload_2
12: putfield #24; //Field FIELD_1:[Ljava/lang/String;
15: dup
16: aload_3
17: putfield #27; //Field FIELD_2:Ljava/lang/String;
20: returnpublic int hashCode();
Code:
0: ldc #30; //int 938313161
2: aload_0
3: getfield #20; //Field FIELD_0:Ljava/lang/String;
6: swap
7: ldc #31; //int 362693231
9: imul
10: swap
11: dup
12: ifnull 21
15: invokevirtual #35; //Method java/lang/Object.hashCode:()I
18: goto 23
21: pop
22: iconst_0
23: iadd
24: aload_0
25: getfield #24; //Field FIELD_1:[Ljava/lang/String;
28: dup
29: ifnull 71
32: astore_1
33: iconst_0
34: istore_2
35: goto 62
38: aload_1
39: iload_2
40: aaload
41: swap
42: ldc #31; //int 362693231
44: imul
45: swap
46: dup
47: ifnull 56
50: invokevirtual #35; //Method java/lang/Object.hashCode:()I
53: goto 58
56: pop
57: iconst_0
58: iadd
59: iinc 2, 1
62: iload_2
63: aload_1
64: arraylength
65: if_icmplt 38
68: goto 72
71: pop
72: aload_0
73: getfield #27; //Field FIELD_2:Ljava/lang/String;
76: swap
77: ldc #31; //int 362693231
79: imul
80: swap
81: dup
82: ifnull 91
85: invokevirtual #35; //Method java/lang/Object.hashCode:()I
88: goto 93
91: pop
92: iconst_0
93: iadd
94: ireturnpublic boolean equals(java.lang.Object);
Code:
0: aload_1
1: instanceof #2; //class net/sf/cglib/core/MethodWrapper$MethodWrapperKey$$KeyFactoryByCGLIB$$d45e49f7
4: ifeq 181
7: aload_0
8: getfield #20; //Field FIELD_0:Ljava/lang/String;
11: aload_1
12: checkcast #2; //class net/sf/cglib/core/MethodWrapper$MethodWrapperKey$$KeyFactoryByCGLIB$$d45e49f7
15: getfield #20; //Field FIELD_0:Ljava/lang/String;
18: dup2
19: ifnonnull 29
22: ifnonnull 35
25: pop2
26: goto 45
29: ifnull 35
32: goto 39
35: pop2
36: goto 181
39: invokevirtual #39; //Method java/lang/Object.equals:(Ljava/lang/Object;)Z
42: ifeq 181
45: aload_0
46: getfield #24; //Field FIELD_1:[Ljava/lang/String;
49: aload_1
50: checkcast #2; //class net/sf/cglib/core/MethodWrapper$MethodWrapperKey$$KeyFactoryByCGLIB$$d45e49f7
53: getfield #24; //Field FIELD_1:[Ljava/lang/String;
56: dup2
57: ifnonnull 67
60: ifnonnull 73
63: pop2
64: goto 141
67: ifnull 73
70: goto 77
73: pop2
74: goto 181
77: dup2
78: arraylength
79: swap
80: arraylength
81: if_icmpeq 88
84: pop2
85: goto 181
88: astore_2
89: astore_3
90: iconst_0
91: istore 4
93: goto 134
96: aload_2
97: iload 4
99: aaload
100: aload_3
101: iload 4
103: aaload
104: dup2
105: ifnonnull 115
108: ifnonnull 121
111: pop2
112: goto 131
115: ifnull 121
118: goto 125
121: pop2
122: goto 181
125: invokevirtual #39; //Method java/lang/Object.equals:(Ljava/lang/Object;)Z
128: ifeq 181
131: iinc 4, 1
134: iload 4
136: aload_2
137: arraylength
138: if_icmplt 96
141: aload_0
142: getfield #27; //Field FIELD_2:Ljava/lang/String;
145: aload_1
146: checkcast #2; //class net/sf/cglib/core/MethodWrapper$MethodWrapperKey$$KeyFactoryByCGLIB$$d45e49f7
149: getfield #27; //Field FIELD_2:Ljava/lang/String;
152: dup2
153: ifnonnull 163
156: ifnonnull 169
159: pop2
160: goto 179
163: ifnull 169
166: goto 173
169: pop2
170: goto 181
173: invokevirtual #39; //Method java/lang/Object.equals:(Ljava/lang/Object;)Z
176: ifeq 181
179: iconst_1
180: ireturn
181: iconst_0
182: ireturnpublic java.lang.String toString();
Code:
0: new #43; //class java/lang/StringBuffer
3: dup
4: invokespecial #44; //Method java/lang/StringBuffer.”":()V
7: aload_0
8: getfield #20; //Field FIELD_0:Ljava/lang/String;
11: dup
12: ifnull 24
15: invokevirtual #46; //Method java/lang/Object.toString:()Ljava/lang/String;
18: invokevirtual #50; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
21: goto 30
24: pop
25: ldc #52; //String null
27: invokevirtual #50; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
30: ldc #54; //String ,
32: invokevirtual #50; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
35: aload_0
36: getfield #24; //Field FIELD_1:[Ljava/lang/String;
39: dup
40: ifnull 110
43: swap
44: ldc #56; //String {
46: invokevirtual #50; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
49: swap
50: astore_1
51: iconst_0
52: istore_2
53: goto 86
56: aload_1
57: iload_2
58: aaload
59: dup
60: ifnull 72
63: invokevirtual #46; //Method java/lang/Object.toString:()Ljava/lang/String;
66: invokevirtual #50; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
69: goto 78
72: pop
73: ldc #52; //String null
75: invokevirtual #50; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
78: ldc #54; //String ,
80: invokevirtual #50; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
83: iinc 2, 1
86: iload_2
87: aload_1
88: arraylength
89: if_icmplt 56
92: dup
93: dup
94: invokevirtual #59; //Method java/lang/StringBuffer.length:()I
97: iconst_2
98: isub
99: invokevirtual #63; //Method java/lang/StringBuffer.setLength:(I)V
102: ldc #65; //String }
104: invokevirtual #50; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
107: goto 116
110: pop
111: ldc #52; //String null
113: invokevirtual #50; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
116: ldc #54; //String ,
118: invokevirtual #50; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
121: aload_0
122: getfield #27; //Field FIELD_2:Ljava/lang/String;
125: dup
126: ifnull 138
129: invokevirtual #46; //Method java/lang/Object.toString:()Ljava/lang/String;
132: invokevirtual #50; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
135: goto 144
138: pop
139: ldc #52; //String null
141: invokevirtual #50; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
144: invokevirtual #66; //Method java/lang/StringBuffer.toString:()Ljava/lang/String;
147: areturn}
(3) JAVAASSIST动态代理接口生成的字节码:
public class com.alibaba.test.performance.dynamicproxy.CountService_$$_javassist_0 extends java.lang.Object implements com.alibaba.test.performance.dynamicproxy.CountService,javassist.util.proxy.ProxyObject{
public static javassist.util.proxy.MethodHandler default_interceptor;public static javassist.util.proxy.MethodFilter _method_filter;
public com.alibaba.test.performance.dynamicproxy.CountService_$$_javassist_0();
Code:
0: aload_0
1: getstatic #19; //Field default_interceptor:Ljavassist/util/proxy/MethodHandler;
4: putfield #21; //Field handler:Ljavassist/util/proxy/MethodHandler;
7: getstatic #23; //Field default_interceptor:Ljavassist/util/proxy/MethodHandler;
10: ifnonnull 20
13: aload_0
14: getstatic #27; //Field javassist/util/proxy/RuntimeSupport.default_interceptor:Ljavassist/util/proxy/MethodHandler;
17: putfield #29; //Field handler:Ljavassist/util/proxy/MethodHandler;
20: aload_0
21: invokespecial #31; //Method java/lang/Object.”":()V
24: returnpublic final boolean _d0equals(java.lang.Object);
Code:
0: aload_0
1: aload_1
2: invokespecial #38; //Method java/lang/Object.equals:(Ljava/lang/Object;)Z
5: ireturnpublic final boolean equals(java.lang.Object);
Code:
0: getstatic #42; //Field _methods_:[Ljava/lang/reflect/Method;
3: astore_2
4: aload_0
5: ldc #43; //String equals
7: ldc #44; //String _d0equals
9: iconst_0
10: ldc #45; //String (Ljava/lang/Object;)Z
12: aload_2
13: invokestatic #49; //Method javassist/util/proxy/RuntimeSupport.find2Methods:(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;[Ljava/lang/reflect/Method;)V
16: aload_0
17: getfield #51; //Field handler:Ljavassist/util/proxy/MethodHandler;
20: aload_0
21: aload_2
22: iconst_0
23: aaload
24: aload_2
25: iconst_1
26: aaload
27: iconst_1
28: anewarray #52; //class java/lang/Object
31: dup
32: iconst_0
33: aload_1
34: aastore
35: invokeinterface #58, 5; //InterfaceMethod javassist/util/proxy/MethodHandler.invoke:(Ljava/lang/Object;Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
40: checkcast #60; //class java/lang/Boolean
43: invokevirtual #64; //Method java/lang/Boolean.booleanValue:()Z
46: ireturnpublic final java.lang.Object _d1clone() throws java.lang.CloneNotSupportedException;
Code:
0: aload_0
1: invokespecial #72; //Method java/lang/Object.clone:()Ljava/lang/Object;
4: areturnprotected final java.lang.Object clone() throws java.lang.CloneNotSupportedException;
Code:
0: getstatic #74; //Field _methods_:[Ljava/lang/reflect/Method;
3: astore_1
4: aload_0
5: ldc #75; //String clone
7: ldc #76; //String _d1clone
9: iconst_2
10: ldc #77; //String ()Ljava/lang/Object;
12: aload_1
13: invokestatic #79; //Method javassist/util/proxy/RuntimeSupport.find2Methods:(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;[Ljava/lang/reflect/Method;)V
16: aload_0
17: getfield #81; //Field handler:Ljavassist/util/proxy/MethodHandler;
20: aload_0
21: aload_1
22: iconst_2
23: aaload
24: aload_1
25: iconst_3
26: aaload
27: iconst_0
28: anewarray #52; //class java/lang/Object
31: invokeinterface #83, 5; //InterfaceMethod javassist/util/proxy/MethodHandler.invoke:(Ljava/lang/Object;Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
36: checkcast #4; //class java/lang/Object
39: areturnpublic final int _d2hashCode();
Code:
0: aload_0
1: invokespecial #88; //Method java/lang/Object.hashCode:()I
4: ireturnpublic final int hashCode();
Code:
0: getstatic #90; //Field _methods_:[Ljava/lang/reflect/Method;
3: astore_1
4: aload_0
5: ldc #91; //String hashCode
7: ldc #92; //String _d2hashCode
9: iconst_4
10: ldc #93; //String ()I
12: aload_1
13: invokestatic #95; //Method javassist/util/proxy/RuntimeSupport.find2Methods:(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;[Ljava/lang/reflect/Method;)V
16: aload_0
17: getfield #97; //Field handler:Ljavassist/util/proxy/MethodHandler;
20: aload_0
21: aload_1
22: iconst_4
23: aaload
24: aload_1
25: iconst_5
26: aaload
27: iconst_0
28: anewarray #52; //class java/lang/Object
31: invokeinterface #99, 5; //InterfaceMethod javassist/util/proxy/MethodHandler.invoke:(Ljava/lang/Object;Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
36: checkcast #101; //class java/lang/Integer
39: invokevirtual #104; //Method java/lang/Integer.intValue:()I
42: ireturnpublic final int count();
Code:
0: getstatic #107; //Field _methods_:[Ljava/lang/reflect/Method;
3: astore_1
4: aload_0
5: ldc #108; //String count
7: aconst_null
8: bipush 6
10: ldc #109; //String ()I
12: aload_1
13: invokestatic #111; //Method javassist/util/proxy/RuntimeSupport.find2Methods:(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;[Ljava/lang/reflect/Method;)V
16: aload_0
17: getfield #113; //Field handler:Ljavassist/util/proxy/MethodHandler;
20: aload_0
21: aload_1
22: bipush 6
24: aaload
25: aload_1
26: bipush 7
28: aaload
29: iconst_0
30: anewarray #52; //class java/lang/Object
33: invokeinterface #115, 5; //InterfaceMethod javassist/util/proxy/MethodHandler.invoke:(Ljava/lang/Object;Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
38: checkcast #101; //class java/lang/Integer
41: invokevirtual #117; //Method java/lang/Integer.intValue:()I
44: ireturnpublic final void _d4finalize() throws java.lang.Throwable;
Code:
0: aload_0
1: invokespecial #123; //Method java/lang/Object.finalize:()V
4: returnprotected final void finalize() throws java.lang.Throwable;
Code:
0: getstatic #125; //Field _methods_:[Ljava/lang/reflect/Method;
3: astore_1
4: aload_0
5: ldc #126; //String finalize
7: ldc #127; //String _d4finalize
9: bipush 8
11: ldc #128; //String ()V
13: aload_1
14: invokestatic #130; //Method javassist/util/proxy/RuntimeSupport.find2Methods:(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;[Ljava/lang/reflect/Method;)V
17: aload_0
18: getfield #132; //Field handler:Ljavassist/util/proxy/MethodHandler;
21: aload_0
22: aload_1
23: bipush 8
25: aaload
26: aload_1
27: bipush 9
29: aaload
30: iconst_0
31: anewarray #52; //class java/lang/Object
34: invokeinterface #134, 5; //InterfaceMethod javassist/util/proxy/MethodHandler.invoke:(Ljava/lang/Object;Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
39: pop
40: returnpublic final java.lang.String _d5toString();
Code:
0: aload_0
1: invokespecial #139; //Method java/lang/Object.toString:()Ljava/lang/String;
4: areturnpublic final java.lang.String toString();
Code:
0: getstatic #141; //Field _methods_:[Ljava/lang/reflect/Method;
3: astore_1
4: aload_0
5: ldc #142; //String toString
7: ldc #143; //String _d5toString
9: bipush 10
11: ldc #144; //String ()Ljava/lang/String;
13: aload_1
14: invokestatic #146; //Method javassist/util/proxy/RuntimeSupport.find2Methods:(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;[Ljava/lang/reflect/Method;)V
17: aload_0
18: getfield #148; //Field handler:Ljavassist/util/proxy/MethodHandler;
21: aload_0
22: aload_1
23: bipush 10
25: aaload
26: aload_1
27: bipush 11
29: aaload
30: iconst_0
31: anewarray #52; //class java/lang/Object
34: invokeinterface #150, 5; //InterfaceMethod javassist/util/proxy/MethodHandler.invoke:(Ljava/lang/Object;Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
39: checkcast #152; //class java/lang/String
42: areturnstatic {};
Code:
0: bipush 12
2: anewarray #155; //class java/lang/reflect/Method
5: putstatic #157; //Field _methods_:[Ljava/lang/reflect/Method;
8: returnpublic void setHandler(javassist.util.proxy.MethodHandler);
Code:
0: aload_0
1: aload_1
2: putfield #161; //Field handler:Ljavassist/util/proxy/MethodHandler;
5: returnjava.lang.Object writeReplace() throws java.io.ObjectStreamException;
Code:
0: aload_0
1: invokestatic #168; //Method javassist/util/proxy/RuntimeSupport.makeSerializedProxy:(Ljava/lang/Object;)Ljavassist/util/proxy/SerializedProxy;
4: areturn}
(5) JAVAASSIST拼接源码生成的字节码:
public class com.alibaba.test.performance.dynamicproxy.CountServiceJavaassistProxy extends java.lang.Object implements com.alibaba.test.performance.dynamicproxy.CountService{
public com.alibaba.test.performance.dynamicproxy.CountService delegate;public com.alibaba.test.performance.dynamicproxy.CountServiceJavaassistProxy();
Code:
0: aload_0
1: invokespecial #12; //Method java/lang/Object.”":()V
4: returnpublic int count();
Code:
0: aload_0
1: getfield #19; //Field delegate:Lcom/alibaba/test/performance/dynamicproxy/CountService;
4: invokeinterface #21, 1; //InterfaceMethod com/alibaba/test/performance/dynamicproxy/CountService.count:()I
9: ireturn}
(6) 用ASM自行生成的字节码:
public class com.alibaba.test.performance.dynamicproxy.CountServiceAsmProxy extends java.lang.Object implements com.alibaba.test.performance.dynamicproxy.CountService{
public com.alibaba.test.performance.dynamicproxy.CountService delegate;public com.alibaba.test.performance.dynamicproxy.CountServiceAsmProxy();
Code:
0: aload_0
1: invokespecial #10; //Method java/lang/Object.”":()V
4: returnpublic int count();
Code:
0: aload_0
1: getfield #16; //Field delegate:Lcom/alibaba/test/performance/dynamicproxy/CountService;
4: invokeinterface #18, 1; //InterfaceMethod com/alibaba/test/performance/dynamicproxy/CountService.count:()I
9: ireturn}
发表评论
-
静态代理之AspectJ编译织入
2019-10-17 08:41 0前面两篇文章都是说的在代码运行时动态的生成class文件达到 ... -
ReentrantLock(重入锁)功能详解和应用演示
2019-10-15 09:54 0https://www.cnblogs.com/taku ... -
Java技术之AQS详解
2019-10-15 09:04 0https://www.jianshu.com/p/da9d ... -
基于AQS实现的Java并发工具类
2019-10-15 09:02 0https://www.cnblogs.com/booths ... -
java线程池ThreadPoolExecutor类使用详解
2019-10-10 17:06 0在《阿里巴巴java开发手册》中指出了线程资源必须通 ... -
java如何实现按指定行读取文件
2019-05-24 18:30 0最近在开发实战中,遇到了一个这样的技术情景: 把 ... -
通过反射把map中的属性赋值到实体类bean对象中
2019-04-12 13:38 0使用过struts2后感觉最方便的就是这个框架能自动把表单 ... -
使用slf4j + Log4j2构建日志
2017-04-07 10:42 0一、背景 Log4j 1.x 在高并发情况下出现死锁导致c ... -
Apache Log4j 2.0值得升级吗
2017-02-08 10:46 0Apache软件基金会最近发布了Log4j 2.0通用版本, ... -
maven deploy到nexus报错:Return code is: 401, ReasonPhrase:Unauthorized
2017-01-16 15:05 0正确 mvn deploy:deploy-file -D ... -
Java四种线程池的使用
2016-12-08 11:10 0Java通过Executors提供四种线程池,分别为:new ... -
Maven类包冲突终极解决小技若干
2016-08-19 14:34 762那句话怎么讲来着的... 引用 如果你爱他,就请让他用 ... -
Linux下Mysql 5.6.21 tar包安装实践
2016-07-25 14:58 3991http://blog.csdn.net/zhanngle ... -
Java8 Lambda表达式教程
2016-06-21 13:36 722http://blog.csdn.net/ioriogami ... -
加密机
2015-12-09 09:57 4752什么是加密机? 加密机是通过国家商用密码主管部门鉴定并批 ... -
maven setting
2015-11-25 16:26 0<?xml version="1.0&quo ... -
SPRING中的线程池ThreadPoolTaskExecutor
2015-11-04 18:20 6060一、初始化 1,直接调用 [java] ... -
解决Maven中使用很多本地jar包的编译问题
2015-10-28 16:58 5390Maven依赖本地非repository中的jar包,依赖j ... -
Spring线程池开发实战及使用spring注解
2015-10-27 11:03 2766作者:chszs,转载需注明。 作者博客主页:http:/ ... -
利用反射调用方法抛出的异常如何被捕获?
2015-10-13 14:41 0我们通常在java开发中采用自定义异常,在业务中遇到 ...
相关推荐
Android动态加载Apk-插件化技术(动态代理方案) 一. 什么是插件化 1. 主App(宿主App)加载插件apk的实现 2. 每个业务组件模块形成一个独立的Apk, 然后通过主App动态加载部署业务组件模块Apk的一种方案 二.插件化的...
8. **性能对比**:相对于JDK的动态代理,CGLib在某些场景下性能更优,因为它避免了接口调用的额外开销。然而,由于涉及到字节码操作,CGLib在初始化阶段可能比JDK代理慢。 9. **使用示例**:创建一个动态代理通常...
本篇文章将详细探讨如何通过Java的动态代理机制来模拟Spring AOP的核心概念。 首先,让我们了解什么是动态代理。在Java中,动态代理主要由`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口...
在构建高性能的Windows Communication Foundation(WCF)解决方案时,我们需要关注多个关键方面,这些方面将直接影响服务的性能、效率和可扩展性。本篇将详细探讨传输层、序列化器、编码器的选择以及客户端和服务端...
4. **性能分析**:从计算开销和通信开销两个方面评估该方案的效率,并与其他相关签名方案进行比较。结果显示,所提出的ABPS方案在保持与现有方案相似的通信开销的同时,显著减少了计算成本。 #### 相关工作概述 - ...
【标题】中所提及的“高效的代理多重盲签名方案”可能意味着所提出的方案在满足安全性要求的同时,具有更好的性能表现。这可能意味着该方案在保持高强度安全性的同时,通过优化算法,降低了计算资源的消耗,并减少了...
2. 独特的接收机设计,低功耗和高性能。 3. 单电源设计可以节省BOM成本。 4. 可编程的SSC可以降低电磁干扰。 5. VGA的输出幅度自动校准算法,可以兼容各种阻抗。 6. DisplayPort自适应均衡算法,适应不同衰减的电缆...
此外,文章还对比了Linux内核编程和用户态编程的优缺点,强调了内核编程在性能优化上的优势。通过实际测试数据,KHttpProxyd的性能表现明显优于其他HTTP代理软件,证明了这种设计和实现策略的有效性。 总的来说,...
java8 stream 源码 Java各种开源库积累 好好学习,天天向上。 演示内容 1)src/main/java org.xpen.audio 播放各种声音格式ogg,mp3,ape,flac org.xpen.chess.puzzle8 ...动态代理方案性能对比,比较了J
在本方案中,Web Polygraph将被用来比较硬件MWG(McAfee Web Gateway)和软件MWG的性能差异。 测试环境基于CentOS 6.5 X86-64操作系统,这是由于Linux系统提供了稳定的基础,并且能够支持Web Polygraph的运行。为了...
代理模式可以用于性能监控或拦截操作,提高代码的灵活性。这些模式的合理运用能提高代码的可读性和可维护性,间接提升性能。 在实际项目中,我们还需要借助各种性能分析工具,如JProfiler、VisualVM等,它们能帮助...
- **性能差异**:NAT因为工作在网络层,通常比工作在更高层的代理服务器速度更快。但如果代理服务器启用了缓存功能,则情况可能有所不同。 - **协议支持**:NAT支持更多的上层协议,几乎涵盖了所有的常见应用层协议...
实验部分可能会展示在不同场景下的性能比较,包括不同基函数下的轨迹质量和规划效率。此外,可能会对比集中式和去中心化方法的优劣,以证明MADER在实时性和安全性方面的优势。 IV. 结论与未来工作 MADER的提出为...
对于性能对比,LVS在处理大量连接时可能有优势,而Nginx在处理动态内容和复杂HTTP逻辑时更出色。 演讲可能详细讲解了LVS和Nginx的安装、配置、优化方法,以及在实际项目中如何选择合适的负载均衡策略。同时,通过...
简介 Ruby On Rails 框架自它提出之日起就受到广泛关注,在“不要重复自己”,“约定优于配置”等思想的指导下,Rails 带给 Web 开发者的是极高的开发效率。 ActiveRecord 的灵活让你再也不用配置繁琐的 Hibernate ...
反向代理服务器是提高WEB服务器性能和安全性的解决方案。它位于本地WEB服务器和Internet之间,承担对原始WEB服务器的静态页面的请求,防止原始服务器过载。反向代理服务器可以降低WEB服务器的负载,提高访问速度,...
当一个类没有实现接口时,CGLIB可以作为JDK动态代理的一种替代方案。它创建目标类的子类,并在子类中拦截方法调用,从而实现动态代理。 2. **与ASM的关系**: - CGLIB底层依赖于ASM库来生成和操作字节码。ASM是一...
经常有朋友困扰于Android上面实现推送的技术,希望知道各种方案的优缺点、性能、开发难度等,于是特意写了这篇文章。 方案一: Google官方的服务: 但,通过对比研究发现C2DM机制存在以下缺点: 1)GCM要求Android...
- **共享存储和集群代理**:利用共享存储技术与集群代理软件配合,可以实现在多台服务器间的数据共享和自动故障转移。 - **高可用网络设备**:如Dolphin SCI互连适配器,能够提供高性能和低延迟的数据传输,非常适合...