如何编写Java代理

对于vmlens (轻量级Java竞争条件捕获器),我们使用Java代理来跟踪字段访问。 这是我们学习的实现此类代理的经验教训。

开始

使用“ static public static void premain(String args,Instrumentation inst)”方法创建一个代理类。 将该类放入一个jar文件中,其中包含指向Agent类的清单。 premain方法将在应用程序的main方法之前调用。

Manifest-Version: 1.0
Ant-Version: Apache Ant 1.9.2
Created-By: 1.8.0_05-b13 (Oracle Corporation)
Built-By: Thomas Krieger
Implementation-Vendor: Anarsoft
Implementation-Title: VMLens Agent
Implementation-Version: 2.0.0.201511181111
Can-Retransform-Classes: true
Premain-Class: com.anarsoft.trace.agent.Agent
Boot-Class-Path: agent_bootstrap.jar

来自vmlens的MANIFEST.MF文件。

类加载器魔术第1部分

代理类将由系统类加载器加载。 但是我们必须避免代理和应用程序使用的类之间的版本冲突。 尤其是代理中使用的框架对于应用程序类应该不可见。 因此,我们使用专用的URLClassLoader来加载所有其他代理类:

// remember the currently used classloader
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
        
// Create and set a special URLClassLoader
URLClassLoader classloader = new URLClassLoader(urlList.toArray(new URL[]{}) , null );
Thread.currentThread().setContextClassLoader(classloader);
    
// Load and execute the agent
String agentName = "com.anarsoft.trace.agent.runtime.AgentRuntimeImpl";
AgentRuntime agentRuntime  =  (AgentRuntime) classloader.loadClass(agentName).newInstance();
    
// reset the classloader
Thread.currentThread().setContextClassLoader(contextClassLoader);

类加载器魔术第2部分

现在,当访问字段时,我们使用asm添加我们的静态回调方法。 为了确保这些类在所有其他类中可见,它们必须由引导类加载器加载。 为此,它们必须位于java包中,并且包含它们的jar必须位于引导类路径中。

package java.anarsoft.trace.agent.bootstrap.callback;

public class FieldAccessCallback {

public static  void getStaticField(int field,int methodId) {
 }

}

vmlens的回调类。 它必须在java包命名空间中才能在所有类中可见。

Boot-Class-Path: agent_bootstrap.jar

vmlens的MANIFEST.MF文件中的引导类路径条目。

VMLens是一种轻量级的Java竞争条件捕获器,是作为Java代理构建的。 我们知道,编写Java代理可能是一件棘手的事情。 因此,如果您有任何问题,请在下面的评论中提问。

翻译自: https://www.javacodegeeks.com/2015/12/write-java-agent.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基本原理: 代理服务器打开一个端口接收浏览器发来的访问某个站点的请求,从请求的字符串中解析出用户想访问哪个网页,让后通过URL对象建立输入流读取相应的网页内容,最后按照web服务器的工作方式将网页内容发送给用户浏览器 源程序: import java.net.*; import java.io.*; public class MyProxyServer { public static void main(String args[]) { try { ServerSocket ss=new ServerSocket(8080); System.out.println("proxy server OK"); while (true) { Socket s=ss.accept(); process p=new process(s); Thread t=new Thread(p); t.start(); } } catch (Exception e) { System.out.println(e); } } }; class process implements Runnable { Socket s; public process(Socket s1) { s=s1; } public void run() { String content=" "; try { PrintStream out=new PrintStream(s.getOutputStream()); BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream())); String info=in.readLine(); System.out.println("now got "+info); int sp1=info.indexOf(' '); int sp2=info.indexOf(' ',sp1+1); String gotourl=info.substring(sp1,sp2); System.out.println("now connecting "+gotourl); URL con=new URL(gotourl); InputStream gotoin=con.openStream(); int n=gotoin.available(); byte buf[]=new byte[1024]; out.println("HTTP/1.0 200 OK"); out.println("MIME_version:1.0"); out.println("Content_Type:text/html"); out.println("Content_Length:"+n); out.println(" "); while ((n=gotoin.read(buf))>=0) { out.write(buf,0,n); } out.close(); s.close(); } catch (IOException e) { System.out.println("Exception:"+e); } } };
好的,我来分别给您演示一下Java中静态代理和动态代理的实现过程。 静态代理: 首先,定义一个接口,比如说: ```java public interface Subject { void request(); } ``` 然后,定义一个实现该接口的被代理类,比如说: ```java public class RealSubject implements Subject { @Override public void request() { System.out.println("RealSubject is handling the request."); } } ``` 接着,定义一个代理类,实现同样的接口,比如说: ```java public class ProxySubject implements Subject { private RealSubject realSubject; public ProxySubject(RealSubject realSubject) { this.realSubject = realSubject; } @Override public void request() { System.out.println("ProxySubject is handling the request."); realSubject.request(); } } ``` 最后,在主函数中,可以这样使用: ```java RealSubject realSubject = new RealSubject(); ProxySubject proxySubject = new ProxySubject(realSubject); proxySubject.request(); ``` 动态代理: 首先,定义一个接口,比如说: ```java public interface Subject { void request(); } ``` 然后,定义一个实现该接口的被代理类,比如说: ```java public class RealSubject implements Subject { @Override public void request() { System.out.println("RealSubject is handling the request."); } } ``` 接着,定义一个InvocationHandler接口的实现类,比如说: ```java public class DynamicProxyHandler implements InvocationHandler { private Object target; public DynamicProxyHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("DynamicProxyHandler is handling the request."); Object result = method.invoke(target, args); return result; } } ``` 最后,在主函数中,可以这样使用: ```java RealSubject realSubject = new RealSubject(); InvocationHandler handler = new DynamicProxyHandler(realSubject); Subject proxySubject = (Subject) Proxy.newProxyInstance(RealSubject.class.getClassLoader(), RealSubject.class.getInterfaces(), handler); proxySubject.request(); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值