《深入理解java虚拟机》读书笔记之类加载案例实战

前言

最近在读《深入理解java虚拟机》,第三部分-虚拟及执行子系统。作者从类文件结构讲到虚拟机类加载机制、虚拟机字节码执行引擎,最后还分析了几种常见的类加载器架构,其中我们就看到了熟悉的动态代理了,最后最后作者提供了一个实战例子:自己动手实现远程执行功能。

在网络上搜索了一下,大部分笔记文章都是在总结理论知识点,本人觉得从实例中验证理论会更有体感,就尝试跟着作者的思路,实现一下这个例子,所谓“纸上得来终觉浅,绝知此事要躬行”

源代码主要是书中(《深入理解java虚拟机》(周志明著第二版(蓝版))的第九章)的代码,资料可下载。

目标

实现客户端编写的代码可以在服务端执行,并能返回服务端执行的结果到客户端。

作者给的思路

解决3个问题

1.如何编译提交到服务器的java代码

[在客户端(本地)编译之后,将字节码而不是java代码传到服务端;如果在服务器端编译的话,传过去java代码,可以使用tools.jar包中的com.sun.tools.javac.Main类来编译java文件,其实和使用javac命令编译时一样,但是需要引入额外的jar包,依赖于sun jdk。]

2.如何执行编译之后的java代码

[让类加载器加载这个类生成的class对象,然后反射调用一下某个方法既可以了,考虑到不实现任何接口,可以借用java中人人皆知的main()方法。考虑更多一点,还需要能够多次加载同一类,因为一般会反复修改代码。]

3.如何收集java代码的执行结果

[考虑到不影响原程序的目的,可以直接在执行的类中,把对System.out的符号引用替换为我们准备的PrintStream的符号引用]

实现

一. 其他按下不说,先把程序跑起来

idea建一个java工程(jdk7),把书中的5个类导入进去。

自己写一个TestClass, 也就是要被执行的“临时代码”。

再写一个RunTest,调用一下。原文中是使用jsp文件来模拟调用,这里我就自己写了一个main方法.

手动编译一下各个文件,build->compile, 没改配置的话,class文件会在out目录下

执行一下,RunTest, 就能看到效果了。不过这么跑,是没有远程传输文件的感觉了,要想有远程的感觉,得搞台服务器,使用idea的remote host,可以尝试一下。文档参考:http://blog.csdn.net/lqleo323/article/details/51153890。 

TestClass.java


package org.fenixsoft.classloading.execute;


/** * @author siyao.hq * @date 18/2/11 */


public class TestClass {


    public static void main(String[] args) {


        System.out.println("siyao is testing! siyao is so lovely!");


    }


}


运行结果:

二. 顺着思路,看看源代码,知其所以然。

1.先看执行类JavaClassExecuter,作者注释还是蛮清楚的。

每次执行execute方法,都会生成一个classloader实例。

2.HotSwapClassLoader 自定义了一个ClassLoader

为啥会有不能多次载入执行类的问题呢?

如果忘了前面内容,这时候可以看一下ClassLoader的源码,就能想起原因了,以及所谓的“双亲委派模型”, parent delegation model。(起初听见这个名词“双亲委派模型”,还以为多么的高深,注意放在了双亲上,还想着难道是意味着两个父类动态选择吗?结果就是parent,我真是想太多了……)

如何解决多次载入执行类问题的呢?

看作者的思路,是使用了defineClass()这个方法,没有自己实现findClass()方法。

翻一翻第七章节,看到作者的一行注释,即“即使自定义了类加载器,强行用defineClass()方法去加载一个以“java.lang”开头的类也不会成功,如果尝试这样做的话,将会收到一个虚拟机自己抛出的“java.lang.SecurityException:Prohibited package name:java.lang”异常”。 这是解释说,在parent delegation model下,保证了一定稳定性,类似rt.jar这种基础类库,不能自己重加载。

这时候再看一下ClassLoader.defineClass()的源码,先读一下注释(又要暴露自己的英文水平了…)。

方法说明中一长段,理解一下,就是把一段字节码转化为类 ,其中后面一段是关于“保护域”ProtectionDomain的说明,也就是最后一个参数,关于ProtectionDomain感觉是又是一章节,粗略理解一下权限控制,类装载器在装载类的时候(或者执行类)会调用安全管理器,安全管理器,则通过判断策略来判断我们是不是允许加载这个类,或者执行某些操作,或者某个文件的读写啊之类的。

defineClass中主要是调用了native的defineClass1,也没啥可操作性了。

网上搜到一个资料,有说到“defineClass 方法可以灵活地用来实现分布式动态计算,hadoop mapreduce应该就是使用了这一方法来保证服务器集群间的处理类的传输和运行。” ,待查查。

热部署插件,比如hotcode,应该也会有类似实现,可查看查看。

此外,一个class 的唯一标识:(类名,包名,加载器名),因为每次加载都生成了一个类加载器实例,所以加载的class是不一样的,可以实现重复加载。

测试了一下,JavaClassExecuter增加一个传入classLoarder的参数的方法,修改RunTest如下,执行结果如图所示,最后一行打印会抛异常。

3.ClassModifier 修改class文件中的常量

这个操作,主要是根据书中第6章关于类文件结构的内容来实现的,替换掉System.out的符号引用。具体方法中的Byte操作,看得我眼带蚊香,果断放弃,知道有这种方法就好了。HackSystem类,ByteUtils主要是支持类。

三、执行测试

我自己刚开始纠结于怎么执行的,是不是一定要到服务器端才能验证出效果,表示确实是实现了远程执行代码。后来发现是有点想歪了,不一定非要到服务器上去执行,本地跑一下,体会一下类加载的过程,也是OK的啦。 作者的实例设计说要得到执行的结果,私以为应该是想让读者验证一下类文件结构。

后记

主要是一篇读书笔记,分享一下主要是自己备忘,如果也有跟我一样的小白同学也可以互相帮助一把^_^ , 光看书多么容易犯困啊....

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342

推荐阅读更多精彩内容