远程执行小工具

   今天想给项目写个远程执行的小工具
1.客户端动态编译要远程执行的代码
2.通过网络将编译好的字节码传输到服务端
3.服务端留一个类装载器的接口
4.对客户端传输过来的字节码做一定修改(复杂了的不好改,修改常量池还是不难实现的,比如需要输出信息到客户端,却又想用System.out输出,修改常量池就好了,不然System.out只能输出在服务端)
5.用自定义的ClassLoader将要执行的类装载到jvm,然后执行,输出信息返回给客户端

这个工具类还是比较强大的(不过也很危险,看怎么用了),可以看到服务端的任何类的变量,也可以执行清除缓存之类的操作。

以前写过这种小玩意儿,不过是在有web容器的环境下,
现在的项目是基于netty的长连接应用,不过也好搞定,把原来代码拿来改了个把小时搞定

首先写个netty server用来接收要执行的字节码(它要跟随应用Server一同启动,也就是说同jvm)
代码太多容易打乱思路,只贴出主要代码(decode):
Java代码 复制代码 收藏代码
  1. class HotSwapPipelineFactory implements ChannelPipelineFactory {
  2. private SimpleChannelHandler messageReceivedHandler = new SimpleChannelHandler() {
  3. @Override
  4. public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
  5. byte[] classByte = (byte[]) e.getMessage(); // decode后的字节码byte数组
  6. // execute内部用自定义ClassLoader加载进jvm然后通过反射执行,返回值为一个String,是返回给客户端的信息,这部分代码就不贴出来了
  7. String resultMsg = JavaClassExecuter.execute(classByte);
  8. byte[] resultByte = resultMsg.getBytes(Charset.forName(Constants.UTF8_CHARSET));
  9. ChannelBuffer buffer = ChannelBuffers.buffer(resultByte.length);
  10. buffer.writeBytes(resultByte);
  11. e.getChannel().write(buffer);
  12. }
  13. };
  14. @Override
  15. public ChannelPipeline getPipeline() throws Exception {
  16. return addHandlers(Channels.pipeline());
  17. }
  18. public ChannelPipeline addHandlers(ChannelPipeline pipeline) {
  19. if (null == pipeline) {
  20. return null;
  21. }
  22. // 这个decoder主要应对消息不完整的情况,虽然是小工具也认真对待吧
  23. pipeline.addLast("hotSwapDecoder", new FrameDecoder() {
  24. @Override
  25. protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
  26. if (buffer.readableBytes() >= 4) {
  27. buffer.markReaderIndex(); // 标记ReaderIndex
  28. int msgBodyLen = buffer.readInt(); // 前四个字节存放消息(字节码)的长度
  29. if (buffer.readableBytes() >= msgBodyLen) {
  30. ChannelBuffer dst = ChannelBuffers.buffer(msgBodyLen);
  31. buffer.readBytes(dst, msgBodyLen);
  32. return dst.array(); // 这就是完整的字节码byte数组了
  33. } else {
  34. buffer.resetReaderIndex();
  35. return null;
  36. }
  37. }
  38. return null;
  39. }
  40. });
  41. pipeline.addLast("hotSwapHandler", messageReceivedHandler);
  42. return pipeline;
  43. }
	class HotSwapPipelineFactory implements ChannelPipelineFactory {

		private SimpleChannelHandler messageReceivedHandler = new SimpleChannelHandler() {

			@Override
			public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
				byte[] classByte = (byte[]) e.getMessage();  // decode后的字节码byte数组
            // execute内部用自定义ClassLoader加载进jvm然后通过反射执行,返回值为一个String,是返回给客户端的信息,这部分代码就不贴出来了
				String resultMsg = JavaClassExecuter.execute(classByte);
				byte[] resultByte = resultMsg.getBytes(Charset.forName(Constants.UTF8_CHARSET));
				ChannelBuffer buffer = ChannelBuffers.buffer(resultByte.length);
				buffer.writeBytes(resultByte);
				e.getChannel().write(buffer);
			}
		};

		@Override
		public ChannelPipeline getPipeline() throws Exception {
			return addHandlers(Channels.pipeline());
		}

		public ChannelPipeline addHandlers(ChannelPipeline pipeline) {
			if (null == pipeline) {
				return null;
			}

        // 这个decoder主要应对消息不完整的情况,虽然是小工具也认真对待吧
			pipeline.addLast("hotSwapDecoder", new FrameDecoder() {

				@Override
				protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
					if (buffer.readableBytes() >= 4) {
						buffer.markReaderIndex();			// 标记ReaderIndex
						int msgBodyLen = buffer.readInt();	// 前四个字节存放消息(字节码)的长度
						if (buffer.readableBytes() >= msgBodyLen) {
							ChannelBuffer dst = ChannelBuffers.buffer(msgBodyLen);
							buffer.readBytes(dst, msgBodyLen);
							return dst.array();  // 这就是完整的字节码byte数组了
						} else {
							buffer.resetReaderIndex();
							return null;
						}
					}
					return null;
				}
			});
			pipeline.addLast("hotSwapHandler", messageReceivedHandler);
			return pipeline;
		}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值