动态代理
Java动态代理的两个主要的类:InvocationHandler,Proxy。Proxy通过newProxyInstance创建代理对象,对应的有个动态代理类, 该方法声明如下:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h);
动态代理创建的是个类似com.sun.proxy.$Proxy1,2,...,n的代理类。它有个构造函数,这个构造函数的参数传入一个InvocationHandler。在创建代理类时:
它首先查找或者生成一个委派的代理类:
/* * Look up or generate the designated proxy class. */ Class<?> cl = getProxyClass0(loader, intfs);
然后通过构造函数创建代理实例:
final Constructor<?> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; if (!Modifier.isPublic(cl.getModifiers())) { AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { cons.setAccessible(true); return null; } }); }
该构造函数参数为一个InvocationHandler:
return cons.newInstance(new Object[]{h});
在这里大家有没有什么疑问?既然是代理,为什么没看到代理是哪个对象?newProxyInstance创建的代理对象到底代理的是哪个对象?这里可能会让人引起误解,newProxyInstance实际上创建一个实现了interfaces参数指定的接口的动态类实例,在调用interfaces参数指定的接口方法时会被h参数的InvocationHandler拦截,也就是interfaces参数指定的接口方法实现在动态类中是交给InvocationHandler处理的。
InvocationHandler:
public interface InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; }invoke方法:
public interface GreetService { public String testString(String s); }
public class GreetServiceImpl implements GreetService { public String testString(String s) { System.out.println(s); return s; } }
class ProxyTargetInvocationHandler implements InvocationHandler { private Object target; public ProxyTargetInvocationHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { method.setAccessible(true); // it's not necessary return method.invoke(target, args); } }
@org.junit.Test public void testStringWithProxyTargetInvocationHandler() { ClassLoader cl = Thread.currentThread().getContextClassLoader(); GreetService greetService = new GreetServiceImpl(); InvocationHandler handler = new ProxyTargetInvocationHandler(greetService); GreetService proxy = (GreetService) Proxy.newProxyInstance(cl, new Class<?>[] {GreetService.class}, handler); System.out.println(proxy.testString("greeting.")); }
借用上面例子中的GreetService,如果InvocationHandler实现如下,下面测试代码运行结果是什么?
class ProxyInvocationHandler implements InvocationHandler { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return method.invoke(proxy, args); } }
@org.junit.Test public void testStringWithProxyInvocationHandler() { GreetService greetService = new GreetServiceImpl(); ClassLoader cl = greetService.getClass().getClassLoader(); InvocationHandler handler = new ProxyInvocationHandler(); GreetService proxy = (GreetService) Proxy.newProxyInstance(cl, new Class<?>[] {GreetService.class}, handler); System.out.println(proxy.testString("greeting.")); }
java.lang.OutOfMemoryError: Java heap space
借用上面例子中的GreetService,如果InvocationHandler实现如下,下面测试代码运行结果是什么?
class ProxyInvocationHandler implements InvocationHandler { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println(proxy); return null; } }
@org.junit.Test public void testStringWithProxyInvocationHandler() { GreetService greetService = new GreetServiceImpl(); ClassLoader cl = greetService.getClass().getClassLoader(); InvocationHandler handler = new ProxyInvocationHandler(); GreetService proxy = (GreetService) Proxy.newProxyInstance(cl, new Class<?>[] {GreetService.class}, handler); System.out.println(proxy.testString("greeting.")); }
java.lang.StackOverflowError
这两个运行结果是不是挺奇怪?第一个报OOM,第二个报栈溢出。
第一个测试代码,运行前如果加上-Xmx1024m,报如下错误:
java.lang.StackOverflowError
这个错误结果是正常的。其实对于第一个测试代码,两个错误结果都是可以理解的,而报这两个不同结果都是因栈溢出导致的,我们在运行前加上-Xmx1024m后,直接报栈溢出错误,这个是期望的错误,也是真正报错的原因。至于报OOM的情况,其实也是由于栈溢出导致,只是由于调用栈太长,报错后打印栈信息时OOM了。
至于第二个测试代码,报栈溢出错误,但从代码上不太容易看出来,并没有直接体现,这里就是简单打印了下proxy:System.out.println(proxy);怎么最后运行报栈溢出呢?这里在打印proxy的时候,实际上调用了proxy的toString()方法,看到这里就跟第一个测试代码差不多了,最后报栈溢出错误了。
RMI
关于Java RMI(RPC)的绑定(bind)、导出(export)以及发现(lookup)
关于Java RMI(RPC)的绑定(bind)和导出(export)
绑定(bind)是将远程对象存根和对应的绑定名称在Registry上进行关联,以便在查找(lookup)是能够根据绑定名称查找绑定的远程对象(实际上市对应的远程对象存根,静态存根或动态存根)。
导出(export)
将对象暴露到网络上,以便中间通过网络可以访问到这个对象,调用它的方法。会启动一个TCPEndpoint,TCPEndpoint对应一个TCPTransport。TCPTransport在指定端口上监听tcp请求,以便接受远程方法调用请求。
TCPTransport会启动一个线程来处理远程方法调用请求的连接。
TCPTransport会创建一个线程池来处理远程方法调用请求:
connectionThreadPool = new ThreadPoolExecutor(0, maxConnectionThreads, threadKeepAliveTime, TimeUnit.MILLISECONDS, new SynchronousQueue(), new ThreadFactory() { public Thread newThread(Runnable var1) { return (Thread)AccessController.doPrivileged(new NewThreadAction(var1, "TCP Connection(idle)", true, true)); } });
TCPTransport通过TCPTransport#handleMessages方法处理远程方法调用请求。
是将远程对象导出到一个对象表。
Java RMI每个远程服务对象都对应一个TCPEndpoint,在Transport层上对应一个TCPTransport。所以基于Java RMI开发时,有多少个远程服务就有多少个对应的TCPEndpoint,都有对应的TCPTransport,他们并不共享Transport。
一个对象能够被其他程序调用,要解决两个问题:
1、首先是这两个程序之间的通信问题
2、方法调用的序列化问题,包括调用的方法以及传参。
可能这两个程序是系统内的两个程序进程,系统内,不跨网络;可能是不同系统之间的两个程序进程,跨网络。
系统内进程间的对象调用情况:
跨网络不同系统之间的对象调用情况:
参考文章:https://lobin.iteye.com/blog/2345976
Java RMI 远程方法调用: Java RPC实现
Java RMI规范
Java序列化机制实现:参考https://lobin.iteye.com/blog/629414 远程方法调用(RMI)章节。
Java 序列化
Java序列化机制实现:参考https://lobin.iteye.com/blog/629414 序列化章节。
Java RMI 实例
新版本java开发rmi服务很方便,不需要通过rmic生成Stub(存根)和Skel(Skeleton),老版本java开发rmi服务还需要生成Stub(存根)和Skel(Skeleton)
import java.rmi.Remote; import java.rmi.RemoteException; public interface FPingTaskService extends Remote { public int fping(int target) throws RemoteException; }
import java.rmi.RemoteException; import java.rmi.server.RMIClientSocketFactory; import java.rmi.server.RMIServerSocketFactory; import java.rmi.server.UnicastRemoteObject; public class FPingTaskServiceImpl extends UnicastRemoteObject implements FPingTaskService { protected FPingTaskServiceImpl() throws RemoteException { } protected FPingTaskServiceImpl(int port) throws RemoteException { super(port); } protected FPingTaskServiceImpl(int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) throws RemoteException { super(port, csf, ssf); } @Override public int fping(int target) throws RemoteException { System.out.println("ping " + target); return 1; } }
import java.rmi.Remote; import java.rmi.RemoteException; public interface RemotePingTaskService extends Remote { public int rping(int target) throws RemoteException; }
import java.rmi.RemoteException; import java.rmi.server.RMIClientSocketFactory; import java.rmi.server.RMIServerSocketFactory; import java.rmi.server.UnicastRemoteObject; public class RemotePingTaskServiceImpl extends UnicastRemoteObject implements RemotePingTaskService { protected RemotePingTaskServiceImpl() throws RemoteException { } protected RemotePingTaskServiceImpl(int port) throws RemoteException { super(port); } protected RemotePingTaskServiceImpl(int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) throws RemoteException { super(port, csf, ssf); } @Override public int rping(int target) throws RemoteException { System.out.println("remote ping " + target); return 1; } }
import java.net.MalformedURLException; import java.rmi.AlreadyBoundException; import java.rmi.Naming; import java.rmi.Remote; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.rmi.server.ExportException; import java.rmi.server.UnicastRemoteObject; import java.util.ArrayList; import java.util.Map; public class ServiceExportor { public static java.util.List<java.util.Map<String, Object>> services; public static int DEFAULT_RMI_PORT = 10999; static { services = new ArrayList<Map<String, Object>>(); java.util.Map<String, Object> map = new java.util.HashMap<String, Object>(); map.put("NAME", "RemotePingTaskService"); map.put("CLASS_NAME", "RemotePingTaskServiceImpl"); // map.put("PORT", 11000); services.add(map); map = new java.util.HashMap<String, Object>(); map.put("NAME", "FPingTaskService"); map.put("CLASS_NAME", "FPingTaskServiceImpl"); map.put("PORT", 10990); services.add(map); } private static void createRegistry(int port) throws RemoteException { if (port != -1) { //java.rmi.registry.Registry registry = java.rmi.registry.LocateRegistry.getRegistry("localhost", port); //System.out.println("--->" + registry); //if (registry == null) { System.out.println("Create registry for localhost on " + port); try { Registry registry = LocateRegistry.createRegistry(port); } catch (ExportException e) { System.out.println("Registry for localhost on " + port + " already exists"); } //} } } private static void export(Remote stub, int port) throws RemoteException { if (! (stub instanceof UnicastRemoteObject)) { if (port == -1) { System.out.println("export " + stub.getClass().getName() + " on an anonymous port"); UnicastRemoteObject.exportObject(stub); } else { System.out.println("export " + stub.getClass().getName() + " on port " + port); UnicastRemoteObject.exportObject(stub, port); } } } public static void main(String[] args) throws Exception { createRegistry(DEFAULT_RMI_PORT); try { for (int i = 0, size = services.size(); i < size; i++) { Map<String, Object> service = services.get(i); String serviceName = (String) service.get("NAME"); String className = (String) service.get("CLASS_NAME"); Object o = service.get("PORT"); int port = -1; if (o != null) { port = ((Integer) o).intValue(); } Class clazz = Class.forName(className); Object object = clazz.newInstance(); if (object instanceof Remote) { Remote stub = (Remote) object; export(stub, port); Naming.bind("rmi://localhost:" + DEFAULT_RMI_PORT + "/" + serviceName, stub); System.out.println("RMI service '" + serviceName + "' on localhost:" + DEFAULT_RMI_PORT + " is binding..."); } else { System.out.println("\"" + className + "\" is not a available RMI service"); } System.out.println("------------------------------------------------------------------------------------------------"); } } catch (ClassNotFoundException e) { throw new ServiceException(e); } catch (RemoteException e) { throw new ServiceException(e); } catch (AlreadyBoundException e) { throw new ServiceException(e); } catch (MalformedURLException e) { throw new ServiceException(e); } } }
其中createRegistry(DEFAULT_RMI_PORT);会启动一个Registry。Registry也可以单独启动,服务启动的时候,服务注册绑定时(将服务绑定bind到某个地址上),将服务注册到单独启动的Registry上。
单独启动Registry:
public class ServiceRegistry { public static int DEFAULT_PORT = 20999; private void start() { Registry registry = null; try { registry = LocateRegistry.createRegistry(DEFAULT_PORT); } catch (RemoteException e) { e.printStackTrace(); } synchronized (this) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { new ServiceRegistry().start(); } }
RMI Registry默认端口为1099。
RMI服务注册绑定地址rmi://host:port/servicename,如果是本地地址localhost可省略。
如rmi://:10999/FPingTaskService,rmi://:10999/RemotePingTaskService
Registry Admin:
public class ServiceRegistryAdmin { public static int DEFAULT_PORT = 20999; private void start() { Registry registry = null; try { registry = LocateRegistry.getRegistry(DEFAULT_PORT); } catch (RemoteException e) { e.printStackTrace(); } try { String[] list = registry.list(); for (String serviceName : list) { System.out.println("service: " + serviceName); } } catch(RemoteException e) { e.printStackTrace(); } synchronized (this) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { new ServiceRegistryAdmin().start(); } }
public class ServiceException extends Exception { public ServiceException() { super(); } public ServiceException(String message) { super(message); } public ServiceException(Throwable cause) { super(cause); } }
启动RMI服务,运行结果如下:
Create registry for localhost on 10999 RMI service 'RemotePingTaskService' on localhost:10999 is binding... ------------------------------------------------------------------------------------------------ RMI service 'FPingTaskService' on localhost:10999 is binding... ------------------------------------------------------------------------------------------------
import java.rmi.Naming; public class ServiceTest { public static void main(String[] args) throws Exception { FPingTaskService fPingTaskService = (FPingTaskService) Naming.lookup("rmi://:10999/FPingTaskService"); System.out.println(fPingTaskService.fping(1234)); RemotePingTaskService remotePingTaskService = (RemotePingTaskService) Naming.lookup("rmi://:10999/RemotePingTaskService"); System.out.println(remotePingTaskService.rping(1234)); } }
启动客户端,调用rmi服务。服务端输出:
ping 1234 remote ping 1234
在上面例子中,FPingTaskService,RemotePingTaskService 服务接口实现RemotePingTaskServiceImpl,FPingTaskServiceImpl继承了UnicastRemoteObject类,在创建服务实例时,会自动export服务对象(默认将服务对象export到端口0上)。
protected UnicastRemoteObject() throws RemoteException { this(0); }
protected UnicastRemoteObject(int port) throws RemoteException { this.port = port; exportObject((Remote) this, port); }
protected UnicastRemoteObject(int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) throws RemoteException { this.port = port; this.csf = csf; this.ssf = ssf; exportObject((Remote) this, port, csf, ssf); }
关键代码:
exportObject((Remote) this, port);
在这个例子中,
FPingTaskService fPingTaskService = (FPingTaskService) Naming.lookup("rmi://:10999/FPingTaskService"); RemotePingTaskService remotePingTaskService = (RemotePingTaskService) Naming.lookup("rmi://:10999/RemotePingTaskService");lookup返回的远程对象是java动态代理对象,而不是类似FPingTaskServiceImpl_Stub,RemotePingTaskServiceImpl_Stub的Stub(存根)对象。
public static RemoteStub exportObject(Remote obj) throws RemoteException public static Remote exportObject(Remote obj, int port) throws RemoteException public static Remote exportObject(Remote obj, int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) throws RemoteException其中public static RemoteStub exportObject(Remote obj) throws RemoteException方法已废弃。
>rmic RemotePingTaskServiceImpl >rmic FPingTaskServiceImpl而如果使用
public static Remote exportObject(Remote obj, int port) throws RemoteException public static Remote exportObject(Remote obj, int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) throws RemoteException
FPingTaskService fPingTaskService = (FPingTaskService) Naming.lookup("rmi://:10999/FPingTaskService"); RemotePingTaskService remotePingTaskService = (RemotePingTaskService) Naming.lookup("rmi://:10999/RemotePingTaskService");
lookup返回的远程对象是类似FPingTaskServiceImpl_Stub,RemotePingTaskServiceImpl_Stub的Stub(存根)对象。
public final class RemotePingTaskServiceImpl_Stub extends RemoteStub implements RemotePingTaskService { private static final long serialVersionUID = 2L; private static Method $method_rping_0; static { try { $method_rping_0 = (class$RemotePingTaskService != null?class$RemotePingTaskService:(class$RemotePingTaskService = class$("RemotePingTaskService"))).getMethod("rping", new Class[]{Integer.TYPE}); } catch (NoSuchMethodException var0) { throw new NoSuchMethodError("stub class initialization failed"); } } public RemotePingTaskServiceImpl_Stub(RemoteRef var1) { super(var1); } public int rping(int var1) throws RemoteException { try { Object var2 = super.ref.invoke(this, $method_rping_0, new Object[]{new Integer(var1)}, -3207680512012333040L); return ((Integer)var2).intValue(); } catch (RuntimeException var3) { throw var3; } catch (RemoteException var4) { throw var4; } catch (Exception var5) { throw new UnexpectedException("undeclared checked exception", var5); } } }
public final class FPingTaskServiceImpl_Stub extends RemoteStub implements FPingTaskService { private static final long serialVersionUID = 2L; private static Method $method_fping_0; static { try { $method_fping_0 = (class$FPingTaskService != null?class$FPingTaskService:(class$FPingTaskService = class$("FPingTaskService"))).getMethod("fping", new Class[]{Integer.TYPE}); } catch (NoSuchMethodException var0) { throw new NoSuchMethodError("stub class initialization failed"); } } public FPingTaskServiceImpl_Stub(RemoteRef var1) { super(var1); } public int fping(int var1) throws RemoteException { try { Object var2 = super.ref.invoke(this, $method_fping_0, new Object[]{new Integer(var1)}, -5354781327026957849L); return ((Integer)var2).intValue(); } catch (RuntimeException var3) { throw var3; } catch (RemoteException var4) { throw var4; } catch (Exception var5) { throw new UnexpectedException("undeclared checked exception", var5); } } }
在这种情况下,
FPingTaskService fPingTaskService = (FPingTaskService) Naming.lookup("rmi://:10999/FPingTaskService"); RemotePingTaskService remotePingTaskService = (RemotePingTaskService) Naming.lookup("rmi://:10999/RemotePingTaskService");lookup返回的远程对象是类似FPingTaskServiceImpl_Stub,RemotePingTaskServiceImpl_Stub的Stub(存根)对象。
import java.rmi.RemoteException; public class FPingTaskServiceImpl_Java1_1_8 implements FPingTaskService { public int fping(int target) throws RemoteException { System.out.println("ping " + target); return 1; } }
import java.rmi.RemoteException; public class RemotePingTaskServiceImpl_Java1_1_8 implements RemotePingTaskService { public int rping(int target) throws RemoteException { System.out.println("remote ping " + target); return 1; } }
import java.net.MalformedURLException; import java.rmi.AlreadyBoundException; import java.rmi.Naming; import java.rmi.Remote; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.rmi.server.ExportException; import java.rmi.server.UnicastRemoteObject; import java.util.*; public class ServiceExportor_Java1_1_8 { public static Vector services; public static int DEFAULT_RMI_PORT = 10999; static { services = new Vector(); Hashtable map = new Hashtable(); map.put("NAME", "RemotePingTaskService"); map.put("CLASS_NAME", "RemotePingTaskServiceImpl_Java1_1_8"); map.put("PORT", new Integer(11000)); services.addElement(map); map = new Hashtable(); map.put("NAME", "FPingTaskService"); map.put("CLASS_NAME", "FPingTaskServiceImpl_Java1_1_8"); map.put("PORT", new Integer(10990)); services.addElement(map); } private static void createRegistry(int port) throws RemoteException { if (port != -1) { //java.rmi.registry.Registry registry = java.rmi.registry.LocateRegistry.getRegistry("localhost", port); //System.out.println("--->" + registry); //if (registry == null) { System.out.println("Create registry for localhost on " + port); try { Registry registry = LocateRegistry.createRegistry(port); } catch (ExportException e) { e.printStackTrace(); System.out.println("Registry for localhost on " + port + " already exists"); } //} } } private static void export(Remote stub, int port) throws RemoteException { if (! (stub instanceof UnicastRemoteObject)) { System.out.println("export " + stub.getClass().getName() + " on an anonymous port"); UnicastRemoteObject.exportObject(stub); } } public static void main(String[] args) throws Exception { createRegistry(DEFAULT_RMI_PORT); try { for (int i = 0, size = services.size(); i < size; i++) { Hashtable service = (Hashtable) services.elementAt(i); String serviceName = (String) service.get("NAME"); String className = (String) service.get("CLASS_NAME"); Object o = service.get("PORT"); int port = -1; if (o != null) { port = ((Integer) o).intValue(); } Class clazz = Class.forName(className); Object object = clazz.newInstance(); if (object instanceof Remote) { Remote stub = (Remote) object; export(stub, port); Naming.bind("rmi://localhost:" + DEFAULT_RMI_PORT + "/" + serviceName, stub); System.out.println("RMI service '" + serviceName + "' on localhost:" + DEFAULT_RMI_PORT + " is binding..."); } else { System.out.println("\"" + className + "\" is not a available RMI service"); } System.out.println("------------------------------------------------------------------------------------------------"); } } catch (ClassNotFoundException e) { e.printStackTrace(); throw new ServiceException_Java1_1_8(e.getMessage()); } catch (RemoteException e) { e.printStackTrace(); throw new ServiceException_Java1_1_8(e.getMessage()); } catch (AlreadyBoundException e) { e.printStackTrace(); throw new ServiceException_Java1_1_8(e.getMessage()); } catch (MalformedURLException e) { e.printStackTrace(); throw new ServiceException_Java1_1_8(e.getMessage()); } } }
public class ServiceException_Java1_1_8 extends Exception { public ServiceException_Java1_1_8() { super(); } public ServiceException_Java1_1_8(String message) { super(message); } }编译后,为rmi服务生成Stub(存根)和Skel(Skeleton):
>rmic RemotePingTaskServiceImpl_Java1_1_8 >rmic FPingTaskServiceImpl_Java1_1_8
public final class FPingTaskServiceImpl_Java1_1_8_Stub extends RemoteStub implements FPingTaskService { private static final Operation[] operations = new Operation[]{new Operation("int fping(int)")}; private static final long interfaceHash = 2769259642710215340L; public FPingTaskServiceImpl_Java1_1_8_Stub() { } public FPingTaskServiceImpl_Java1_1_8_Stub(RemoteRef var1) { super(var1); } public int fping(int var1) throws RemoteException { try { RemoteCall var2 = super.ref.newCall(this, operations, 0, 2769259642710215340L); try { ObjectOutput var3 = var2.getOutputStream(); var3.writeInt(var1); } catch (IOException var15) { throw new MarshalException("error marshalling arguments", var15); } super.ref.invoke(var2); int var19; try { ObjectInput var6 = var2.getInputStream(); var19 = var6.readInt(); } catch (IOException var13) { throw new UnmarshalException("error unmarshalling return", var13); } finally { super.ref.done(var2); } return var19; } catch (RuntimeException var16) { throw var16; } catch (RemoteException var17) { throw var17; } catch (Exception var18) { throw new UnexpectedException("undeclared checked exception", var18); } } }
public final class FPingTaskServiceImpl_Java1_1_8_Skel implements Skeleton { private static final Operation[] operations = new Operation[]{new Operation("int fping(int)")}; private static final long interfaceHash = 2769259642710215340L; public Operation[] getOperations() { return (Operation[])operations.clone(); } public void dispatch(Remote var1, RemoteCall var2, int var3, long var4) throws Exception { if(var4 != 2769259642710215340L) { throw new SkeletonMismatchException("interface hash mismatch"); } else { FPingTaskServiceImpl_Java1_1_8 var6 = (FPingTaskServiceImpl_Java1_1_8)var1; switch(var3) { case 0: int var7; try { ObjectInput var10 = var2.getInputStream(); var7 = var10.readInt(); } catch (IOException var15) { throw new UnmarshalException("error unmarshalling arguments", var15); } finally { var2.releaseInputStream(); } int var8 = var6.fping(var7); try { ObjectOutput var9 = var2.getResultStream(true); var9.writeInt(var8); return; } catch (IOException var14) { throw new MarshalException("error marshalling return", var14); } default: throw new UnmarshalException("invalid method number"); } } } public FPingTaskServiceImpl_Java1_1_8_Skel() { } }
public final class RemotePingTaskServiceImpl_Java1_1_8_Stub extends RemoteStub implements RemotePingTaskService { private static final Operation[] operations = new Operation[]{new Operation("int rping(int)")}; private static final long interfaceHash = -3061403402385181673L; public RemotePingTaskServiceImpl_Java1_1_8_Stub() { } public RemotePingTaskServiceImpl_Java1_1_8_Stub(RemoteRef var1) { super(var1); } public int rping(int var1) throws RemoteException { try { RemoteCall var2 = super.ref.newCall(this, operations, 0, -3061403402385181673L); try { ObjectOutput var3 = var2.getOutputStream(); var3.writeInt(var1); } catch (IOException var15) { throw new MarshalException("error marshalling arguments", var15); } super.ref.invoke(var2); int var19; try { ObjectInput var6 = var2.getInputStream(); var19 = var6.readInt(); } catch (IOException var13) { throw new UnmarshalException("error unmarshalling return", var13); } finally { super.ref.done(var2); } return var19; } catch (RuntimeException var16) { throw var16; } catch (RemoteException var17) { throw var17; } catch (Exception var18) { throw new UnexpectedException("undeclared checked exception", var18); } } }
public final class RemotePingTaskServiceImpl_Java1_1_8_Skel implements Skeleton { private static final Operation[] operations = new Operation[]{new Operation("int rping(int)")}; private static final long interfaceHash = -3061403402385181673L; public Operation[] getOperations() { return (Operation[])operations.clone(); } public void dispatch(Remote var1, RemoteCall var2, int var3, long var4) throws Exception { if(var4 != -3061403402385181673L) { throw new SkeletonMismatchException("interface hash mismatch"); } else { RemotePingTaskServiceImpl_Java1_1_8 var6 = (RemotePingTaskServiceImpl_Java1_1_8)var1; switch(var3) { case 0: int var7; try { ObjectInput var10 = var2.getInputStream(); var7 = var10.readInt(); } catch (IOException var15) { throw new UnmarshalException("error unmarshalling arguments", var15); } finally { var2.releaseInputStream(); } int var8 = var6.rping(var7); try { ObjectOutput var9 = var2.getResultStream(true); var9.writeInt(var8); return; } catch (IOException var14) { throw new MarshalException("error marshalling return", var14); } default: throw new UnmarshalException("invalid method number"); } } } public RemotePingTaskServiceImpl_Java1_1_8_Skel() { } }
>java ServiceExportor_Java1_1_8 Create registry for localhost on 10999 export RemotePingTaskServiceImpl_Java1_1_8 on an anonymous port RMI service 'RemotePingTaskService' on localhost:10999 is binding... -------------------------------------------------------------------------------- ---------------- export FPingTaskServiceImpl_Java1_1_8 on an anonymous port RMI service 'FPingTaskService' on localhost:10999 is binding... -------------------------------------------------------------------------------- ----------------
import java.rmi.Naming; public class ServiceTest_Java1_1_8 { public static void main(String[] args) throws Exception { FPingTaskService fPingTaskService = (FPingTaskService) Naming.lookup("rmi://:10999/FPingTaskService"); int result = fPingTaskService.fping(1234); System.out.println(result); RemotePingTaskService remotePingTaskService = (RemotePingTaskService) Naming.lookup("rmi://:10999/RemotePingTaskService"); System.out.println(remotePingTaskService.rping(1234)); } }启动客户端,调用rmi服务。服务端输出:
ping 1234 remote ping 1234
JNI
GetMethodID函数声明如下:
jmethodID (JNICALL *GetMethodID) (JNIEnv *env, jclass clazz, const char *name, const char *sig);
获取Java对象方法的jmethodID。包括构造方法,构造方法是一种特殊的方法,但在JVM层面和其他的方式是一样的。
参数说明:
env: 上面已经说明
clazz:表示对象类,如Object.class。
name:方法名,如果是得到构造方法的jmethodID,该参数固定为<init>。
sig:方法签名,形式如下:
(参数类型签名列表)返回类型签名。
如无参构造方法:public JniNewTestObjectX()
或者public void testMethod()方法定义,它的签名为:
()V
如无参构造方法:public JniNewTestObjectX(int i, String s)
或者public void testMethod(int i, String s)方法定义,它的签名为:
(ILjava/lang/String;)V
Java JNI: Java 本机接口可以采用C开发,也支持C++。
例子:
C开发的例子。
public class JniCallMethodReturnVoidTest { static { System.loadLibrary("libjnitest"); } public static void main(String[] args) { JniNewTest obj = new JniNewTest(); obj.testMethod(); } } class JniNewTest { public native void testMethod(); }
>javac JniCallMethodReturnVoidTest.java
>javah -jni -d . JniNewTest
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class JniNewTest */ #ifndef _Included_JniNewTest #define _Included_JniNewTest #ifdef __cplusplus extern "C" { #endif /* * Class: JniNewTest * Method: testMethod * Signature: ()V */ JNIEXPORT void JNICALL Java_JniNewTest_testMethod (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
实现:
#include "JniNewTest.h" JNIEXPORT void JNICALL Java_JniNewTest_testMethod (JNIEnv *env, jobject jobj) { printf("debug: Java_JniNewTest_testMethod.\n"); }
>cl /GR /GX /W3 /ID:\usr\bin\jdk1.6.0_12\include /ID:\usr\bin\jdk1.6.0_12\include\win32 /c /Fo.\ JniNewTest.c
>link /DLL /OUT:.\libjnitest.dll .\JniNewTest.obj
>java JniCallMethodReturnVoidTest debug: Java_JniNewTest_testMethod.
Java native开发
目录结构:
>tree /F .
Folder PATH listing for volume D
Volume serial number is F075-351A
└───com
└───jx
com_jx_Object.c
com_jx_Object.dll
com_jx_Object.exp
com_jx_Object.h
com_jx_Object.lib
com_jx_Object.obj
libobj.dll
libobj.exp
libobj.lib
Object.class
Object.java
ObjectTest.java
Object:
package com.jx; public class Object { public native int addr(); static { System.loadLibrary("libobj"); } }
>javac com\jx\Object.java
>javah -jni -d com\jx com.jx.Object
com_jx_Object.h:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_jx_Object */ #ifndef _Included_com_jx_Object #define _Included_com_jx_Object #ifdef __cplusplus extern "C" { #endif /* * Class: com_jx_Object * Method: addr * Signature: ()I */ JNIEXPORT jint JNICALL Java_com_jx_Object_addr (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
com_jx_Object.c:
#include <stdio.h> #include "com_jx_Object.h" JNIEXPORT jint JNICALL Java_com_jx_Object_addr (JNIEnv *env, jobject jobj) { printf("Java_com_jx_Object_addr.\n"); return 0; }
编译:
>cl /GX /W3 /ID:\usr\bin\jdk1.8.0_101\include /ID:\usr\bin\jdk1.8.0_101\include\win32 /c /Fo.\ *.c连接生成库文件:
>link /DLL /OUT:.\libobj.dll .\*.obj
也可以使用以下命令一次就生成库文件
# 也可以使用以下命令一次就生成库文件: >cl /ID:\usr\bin\jdk1.8.0_101\include /ID:\usr\bin\jdk1.8.0_101\include\win32 /LD com_jx_Object.c
将生成的库文件libobj.dll放在path目录下:
public static void main(String[] args) { String libPath = System.getProperty("java.library.path"); System.out.println(libPath); Object obj = new Object(); obj.addr(); }
<java.library.path> Java_com_jx_Object_addr.Java JNI开发实例:实例化Java对象
class JniNewTestObject { public String toString() { return super.toString() + ": jni new object."; } }
class JniNewTestObjectX { private int i; private String s; public JniNewTestObjectX() { } public JniNewTestObjectX(int i, String s) { this.i = i; this.s = s; } public int i() { return i; } public String s() { return s; } public String toString() { return super.toString() + ": jni new object."; } }
abstract class JniNewTestAbstractObject { public String toString() { return super.toString() + ": jni new object."; } }
class JniNewTestObjectConstructor { public native JniNewTestObject constructJniNewTestObject(Class<?> clazz); public native JniNewTestObjectX constructJniNewTestObjectX(Class<?> clazz); public native JniNewTestObjectX constructJniNewTestObjectX(Class<?> clazz, int i, String s); public native JniNewTestAbstractObject constructJniNewTestAbstractObject(Class<?> clazz); }
public class JniNewObjectTest { static { System.loadLibrary("libjnitest"); } public static void main(String[] args) { JniNewTestObjectConstructor constructor = new JniNewTestObjectConstructor(); JniNewTestObject obj = constructor.constructJniNewTestObject(JniNewTestObject.class); if (obj == null) { System.out.println("construct fail."); } else { System.out.println(obj.toString()); } JniNewTestObjectX objx1 = constructor.constructJniNewTestObjectX(JniNewTestObjectX.class); if (objx1 == null) { System.out.println("construct fail."); } else { System.out.println(objx1.toString()); System.out.println(objx1.i()); System.out.println(objx1.s()); } JniNewTestObjectX objx2 = constructor.constructJniNewTestObjectX(JniNewTestObjectX.class, 1234, "this is 1234."); if (objx2 == null) { System.out.println("construct fail."); } else { System.out.println(objx2.toString()); System.out.println(objx2.i()); System.out.println(objx2.s()); } JniNewTestAbstractObject aobj = constructor.constructJniNewTestAbstractObject(JniNewTestAbstractObject.class); if (aobj == null) { System.out.println("construct fail."); } else { System.out.println(aobj.toString()); } } }
>javac JniNewObjectTest.java为JniNewTestObjectConstructor生成本机接口:JniNewTestObjectConstructor.h
>javah -jni -d . JniNewTestObjectConstructor
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class JniNewTestObjectConstructor */ #ifndef _Included_JniNewTestObjectConstructor #define _Included_JniNewTestObjectConstructor #ifdef __cplusplus extern "C" { #endif /* * Class: JniNewTestObjectConstructor * Method: constructJniNewTestObject * Signature: (Ljava/lang/Class;)LJniNewTestObject; */ JNIEXPORT jobject JNICALL Java_JniNewTestObjectConstructor_constructJniNewTestObject (JNIEnv *, jobject, jclass); /* * Class: JniNewTestObjectConstructor * Method: constructJniNewTestObjectX * Signature: (Ljava/lang/Class;)LJniNewTestObjectX; */ JNIEXPORT jobject JNICALL Java_JniNewTestObjectConstructor_constructJniNewTestObjectX__Ljava_lang_Class_2 (JNIEnv *, jobject, jclass); /* * Class: JniNewTestObjectConstructor * Method: constructJniNewTestObjectX * Signature: (Ljava/lang/Class;ILjava/lang/String;)LJniNewTestObjectX; */ JNIEXPORT jobject JNICALL Java_JniNewTestObjectConstructor_constructJniNewTestObjectX__Ljava_lang_Class_2ILjava_lang_String_2 (JNIEnv *, jobject, jclass, jint, jstring); /* * Class: JniNewTestObjectConstructor * Method: constructJniNewTestAbstractObject * Signature: (Ljava/lang/Class;)LJniNewTestAbstractObject; */ JNIEXPORT jobject JNICALL Java_JniNewTestObjectConstructor_constructJniNewTestAbstractObject (JNIEnv *, jobject, jclass); #ifdef __cplusplus } #endif #endif
#include "JniNewTestObjectConstructor.h" JNIEXPORT jobject JNICALL Java_JniNewTestObjectConstructor_constructJniNewTestObject(JNIEnv *env, jobject jobj, jclass jclazz) { jmethodID m_id = NULL; jobject obj = NULL; m_id = (*env)->GetMethodID(env, jclazz, "<init>", "()V"); if (m_id == NULL) { printf("err: GetMethodID, no constructor with no args."); return NULL; } obj = (*env)->NewObject(env, jclazz, m_id); // public JniNewTestObject() if (obj == NULL) { printf("err: NewObject, return null."); return NULL; } return obj; } JNIEXPORT jobject JNICALL Java_JniNewTestObjectConstructor_constructJniNewTestObjectX__Ljava_lang_Class_2(JNIEnv *env, jobject jobj, jclass jclazz) { jmethodID m_id = NULL; jobject obj = NULL; m_id = (*env)->GetMethodID(env, jclazz, "<init>", "()V"); if (m_id == NULL) { printf("err: GetMethodID, no constructor with no args."); return NULL; } obj = (*env)->NewObject(env, jclazz, m_id); // public JniNewTestObjectX() if (obj == NULL) { printf("err: NewObject, return null."); return NULL; } return obj; } JNIEXPORT jobject JNICALL Java_JniNewTestObjectConstructor_constructJniNewTestObjectX__Ljava_lang_Class_2ILjava_lang_String_2(JNIEnv *env, jobject jobj, jclass jclazz, jint i, jstring s) { jmethodID m_id = NULL; jobject obj = NULL; m_id = (*env)->GetMethodID(env, jclazz, "<init>", "(ILjava/lang/String;)V"); if (m_id == NULL) { printf("err: GetMethodID, no constructor with no args."); return NULL; } obj = (*env)->NewObject(env, jclazz, m_id, i, s); // public JniNewTestObjectX(int i, String s) if (obj == NULL) { printf("err: NewObject, return null."); return NULL; } return obj; } JNIEXPORT jobject JNICALL Java_JniNewTestObjectConstructor_constructJniNewTestAbstractObject(JNIEnv *env, jobject jobj, jclass jclazz) { jmethodID m_id = NULL; jobject obj = NULL; m_id = (*env)->GetMethodID(env, jclazz, "<init>", "()V"); if (m_id == NULL) { printf("err: GetMethodID, no constructor with no args."); return NULL; } obj = (*env)->NewObject(env, jclazz, m_id); // public JniNewTestAbstractObject(), class JniNewTestAbstractObject declares abstract. if (obj == NULL) { printf("err: NewObject, return null."); return NULL; } return obj; }
>cl /GR /GX /W3 /ID:\usr\bin\jdk1.6.0_12\include /ID:\usr\bin\jdk1.6.0_12\include\win32 /c /Fo.\ *.c
>link /DLL /OUT:.\libjnitest.dll .\*.obj运行结果:
>java JniNewObjectTest JniNewTestObject@1fb8ee3: jni new object. JniNewTestObjectX@14318bb: jni new object. 0 null JniNewTestObjectX@ca0b6: jni new object. 1234 this is 1234. err: NewObject, return null.Exception in thread "main" java.lang.InstantiationEx ception: JniNewTestAbstractObject at JniNewTestObjectConstructor.constructJniNewTestAbstractObject(Native Method) at JniNewObjectTest.main(JniNewObjectTest.java:33)
Security
Java Security API Provider:
java.security.Provider
一些实现:
sun.security.provider.Sun
sun.security.ec.SunEC
com.sun.crypto.provider.SunJCE
sun.security.ssl.SunJSSE
sun.security.pkcs11.SunPKCS11
sun.security.jgss.SunProvider
sun.security.smartcardio.SunPCSC
com.sun.deploy.security.MozillaJSSProvider
com.sun.deploy.security.MSCryptoProvider
sun.security.mscapi.SunMSCAPI
org.spongycastle.jce.provider.BouncyCastleProvider
java.lang.SecurityException: JCE cannot authenticate the provider SC
at javax.crypto.Cipher.getInstance(Cipher.java:657)
at spongycastle.RSATest.test1(RSATest.java:66)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.util.jar.JarException: file:/E:/.m2/com/madgag/spongycastle/prov/1.58.0.0/prov-1.58.0.0.jar has unsigned entries - org/spongycastle/jce/MultiCertStoreParameters.class
at javax.crypto.JarVerifier.verifySingleJar(JarVerifier.java:464)
at javax.crypto.JarVerifier.verifyJars(JarVerifier.java:322)
at javax.crypto.JarVerifier.verify(JarVerifier.java:250)
at javax.crypto.JceSecurity.verifyProviderJar(JceSecurity.java:160)
at javax.crypto.JceSecurity.getVerificationResult(JceSecurity.java:186)
at javax.crypto.Cipher.getInstance(Cipher.java:653)
... 24 more
DI/IOC
public class Test { @org.junit.Test public void test1() { HK2 hk2 = HK2.get(); Services services = hk2.create(null, new Module[0]); DynamicBinderFactory dynamicBinderFactory = services.bindDynamically(); Binder binder = dynamicBinderFactory.bind(ServiceImpl.class, ServiceImpl.class, Service.class); ResolvedBinder resolvedBinder = binder.to(ServiceImpl.class); resolvedBinder.in(Singleton.class); binder = dynamicBinderFactory.bind(ServiceImpl1.class); resolvedBinder = binder.to(ServiceImpl1.class); resolvedBinder.in(Singleton.class); binder = dynamicBinderFactory.bind(ServiceImpl2.class); resolvedBinder = binder.to(ServiceImpl2.class); resolvedBinder.in(Singleton.class); dynamicBinderFactory.commit(); ServiceLocator serviceLocator = services.byType(ServiceImpl.class); ServiceImpl serviceImpl = (ServiceImpl) serviceLocator.get(); serviceImpl.name(); serviceLocator = services.byType(ServiceImpl1.class); ServiceImpl1 serviceImpl1 = (ServiceImpl1) serviceLocator.get(); serviceImpl1.name(); serviceLocator = services.byType(ServiceImpl2.class); ServiceImpl2 serviceImpl2 = (ServiceImpl2) serviceLocator.get(); serviceImpl2.name(); System.out.println(); } @org.junit.Test public void test2() { HK2 hk2 = HK2.get(); Services services = hk2.create(null, new Module[0]); DynamicBinderFactory dynamicBinderFactory = services.bindDynamically(); Binder binder = dynamicBinderFactory.bind(Service.class); ResolvedBinder resolvedBinder = binder.to(ServiceImpl.class); resolvedBinder.in(Singleton.class); binder = dynamicBinderFactory.bind(ServiceImpl.class); resolvedBinder = binder.to(ServiceImpl.class); resolvedBinder.in(Singleton.class); binder = dynamicBinderFactory.bind(ServiceImpl1.class); resolvedBinder = binder.to(ServiceImpl1.class); resolvedBinder.in(Singleton.class); binder = dynamicBinderFactory.bind(ServiceImpl2.class); resolvedBinder = binder.to(ServiceImpl2.class); resolvedBinder.in(Singleton.class); dynamicBinderFactory.commit(); ServiceLocator serviceLocator = services.byType(ServiceImpl.class); ServiceImpl serviceImpl = (ServiceImpl) serviceLocator.get(); serviceImpl.name(); serviceLocator = services.byType(ServiceImpl1.class); ServiceImpl1 serviceImpl1 = (ServiceImpl1) serviceLocator.get(); serviceImpl1.name(); serviceLocator = services.byType(ServiceImpl2.class); ServiceImpl2 serviceImpl2 = (ServiceImpl2) serviceLocator.get(); serviceImpl2.name(); System.out.println(); } }
public class Test { public static void main(String[] args) { ServiceLocator locator = ServiceLocatorFactory.getInstance().create("default"); DynamicConfigurationService dynamicConfigurationService = locator.getService(DynamicConfigurationService.class); DynamicConfiguration config = dynamicConfigurationService.createDynamicConfiguration(); config.bind(BuilderHelper.link(ServiceImpl.class).to(ServiceImpl.class).to(Service.class).in(Singleton.class).build()); config.bind(BuilderHelper.link(ServiceImpl1.class).to(ServiceImpl1.class).in(Singleton.class).build()); config.bind(BuilderHelper.link(ServiceImpl2.class).to(ServiceImpl2.class).in(Singleton.class).build()); config.commit(); ServiceLocator newLocator = ServiceLocatorFactory.getInstance().find("default"); ServiceImpl service = locator.getService(ServiceImpl.class); System.out.println(service); service.name(); ServiceImpl1 service1 = locator.getService(ServiceImpl1.class); System.out.println(service1); service1.name(); ServiceImpl2 service2 = locator.getService(ServiceImpl2.class); System.out.println(service2); service2.name(); } }
相关推荐
Java网络高级编程Java网络高级编程Java网络高级编程Java网络高级编程Java网络高级编程Java网络高级编程Java网络高级编程Java网络高级编程Java网络高级编程Java网络高级编程Java网络高级编程Java网络高级编程
Java Web高级编程pdf含下载地址和源码,《Java Web高级编程:涵盖WebSockets、Spring Framework、JPA 》面向的读者是已经了解Java SE、SQL和基本的HTML,准备将他们的Java编码技能提升到更高水平的程序员。...
《Java并发编程的艺术》是一本全面探讨Java并发编程技术的专业书籍,它深入剖析了Java并发机制的底层实现,如volatile、synchronized等关键技术的工作原理,并详细讲解了线程池、并发容器等高级并发工具的使用。...
Java网络高级编程是Java开发中的一个重要领域,它涵盖了网络通信的各种技术和实现,包括TCP/IP协议栈、套接字编程、HTTP、HTTPS、WebSocket等。在深入这个主题之前,我们需要了解一些基本概念。 首先,Java提供了...
Java服务器高级编程是Java开发领域中的重要主题,涵盖了在服务器端使用Java技术构建高效、可扩展和稳定的网络应用。这份资料可能包含了一系列深入的教程、最佳实践和实战案例,旨在帮助开发者提升在Java服务器端开发...
《Java网络高级编程源码》是由人民邮电出版社出版,由金勇华和曲俊生两位专家编著的一本深入探讨Java网络编程的专著。这本书涵盖了Java在互联网开发中的高级应用,旨在帮助读者理解并掌握Java网络编程的核心技术。 ...
Java数据库高级编程宝典
根据提供的信息,《Java游戏高级编程》是一本关于Java游戏开发的专业书籍。虽然给出的部分内容主要集中在如何加入学习交流群以及获取历史教学视频的方式,并没有直接提及书中的具体内容,但我们可以根据书名、描述及...
java高手真经 高级编程卷:java.web高级开发技术.刘中兵java研究室
根据给定的文件标题“Java网络高级编程1.pdf”以及其描述和标签,我们可以推断出这份文档主要聚焦于Java语言在网络编程领域的高级应用。Java作为一种广泛应用的编程语言,在网络编程方面提供了丰富的API和框架,使得...
《Java网络高级编程》这本书是Java开发者深入理解网络编程的重要参考资料。它涵盖了多个关键主题,旨在帮助程序员构建高效、安全的网络应用。以下是对这些知识点的详细解释: 1. **网络进程通信**:网络进程通信是...
Java服务器高级编程.pdf
Java数据库高级编程宝典.isoJava数据库高级编程宝典.iso
Java高级编程涵盖了许多关键主题,这些主题在Java开发中至关重要,尤其对于提升程序员的技能水平和项目效率。以下是对每个章节的详细解释: 1. **Ch01 泛型和泛型接口** - **泛型**:泛型是Java 5引入的一个重要...
以下将详细讨论《JAVA并发编程实践》和《Java网络高级编程》两本书中涵盖的关键知识点。 首先,让我们关注并发编程。并发编程是现代多核处理器系统中不可或缺的一部分,它允许程序同时执行多个任务,从而提高系统...
Java数据库高级编程宝典.part03