您的位置:首页 > 其它

在没有源码的情况下修改.class文件

2016-08-25 12:25 281 查看
写这个博文是因为我自己遇到了问题,不打算大包大揽的详细解释,没有这个能力,也没有这意愿。理由很简单,只是因为害怕遗忘。。。

类似的经历不知是否是常见的情况,总之说说的我的问题:

先发发牢骚,诺记这个公司现在越来越差其实是有原因的,网上很多文章的分析,都有各方面的道理。但在我看来,其中一个原因就是在技术上的迟缓,固步自封,瞻前顾后:

怎么讲,如果要用一个稍微新一点的框架,比如electron,公司内部就需要审核,写文档解释为什么用这个东西,有没有替代方案,然后会有一堆的专家来向你提问。如果这个框架里面的代码,文件稍微多一点,不好意思,Reject,担心maintenance的问题。

所以现在的问题就变成:公司里面的所有软件都是用的很老的框架:

像eclipse link这样的JPA现在还有几个人用?

有人听过vaadin吗?

除了银行,软件公司有大规模用ejb3.1的吗?

还有谁用Liferay作为基本框架去开发网站?

虽然有上进的开发人员还在持续学习,跟进,最新的技术,但公司的很多项目已经没法也不愿意使用这些新技术了。所以普遍看到的现象是,诺记内部的大部分开发人员,经过多年的工作,都成了业务专家,但从软件工程师的角度,却早已落后于时代,这是一个双输的局面,公司没法从员工身上获得创新的驱动力,员工又因为公司的迟缓,不愿改变,而在技术上停滞不前。甚至还有很多30,40岁的老技术人员还用着那些早已淘汰的语言,而没写过一行c++,java代码,更不知道javascript, python, ruby, swift这些语言,和背后更多的框架,事业和公司绑定的如此之深,公司进,则我进,公司退,则我退,公司亡,则失业

好了,牢骚发完。说具体的问题:

所在的项目是搭建在liferay 6.1.1.ga2上面,这个东西说老其实也不老,发布至今,四年而已。打算在上面使用spring mvc + thymeleaf来开发一个新的portlet应用。spring mvc + jsp是没有问题,但spring mvc + thymeleaf却有问题。

因为在Liferay上,我们只能开发portlet,在使用spring mvc时,我们需要加载相关的类,但因为liferay的bug,导致相关资源没能正确加载,详见下文:

We have the structure where applicationContext.xml contains shared beans (service layer, dao layer and such) and is loaded by org.springframework.web.context.ContextLoaderListener . Additionally all portlets have their own context loading MVC related beans (controllers, view resolvers, etc).

Generated listeners in web.xml on version 6.1 GA1:

org.springframework.web.context.ContextLoaderListener

com.liferay.portal.kernel.servlet.SerializableSessionAttributeListener

com.liferay.portal.kernel.servlet.PortletContextListener

After upgrading to Liferay 6.1 GA2 deployment sorts listeners in web.xml alphabetically:

com.liferay.portal.kernel.servlet.PluginContextListener

com.liferay.portal.kernel.servlet.SerializableSessionAttributeListener

org.springframework.web.context.ContextLoaderListener

This causes portlet context to be loaded first and dependent beans from application context are missing.

因此,我们需要在liferay上修复这个bug。最容易的解决方案当然是升级liferay。

但很多项目都是在liferay的基础上开发的,我们只是其中的一个Portlet,在诺记,你要想升级平台的版本,比登天还难吧,因为其他项目组肯定要跳出来,“升级之后,谁来确保升级带来的变动不会对已经开发完的软件产生影响?谁来做来做全面的测试?我们为什么要收到你的影响”。

好吧,不升级,我能否打个补丁,只更改一个class文件,把改动最小化总可以了吧?

先来看看官方的fixed:

https://github.com/vpugar/liferay-portal/commit/6f11feed226745a3ebbcf2b1e0fa4ec12e9a8128

只有几行代码,涉及到一个文件。我们要做的就是把jar包中的BaseDeployer.class文件替换掉,然后再使用更新后的jar包。(有人说,你这哪叫没源码,明明git上有源码,好吧,git上确实有源码,但是一共有140万个文件,我下到200M之后,才4%的进度,我放弃,我就尝试在没有源码的情况下打开吧)

第一步,反编译

通过7z或者其他工具,打开jar包,找到对应的class文件,双击打开(如果你安装了intellij或者eclipse, 系统会默认关联class文件,为你打开,并且反编译,所以,工欲善其事,必先利其器,选择一个好的IDE相当重要)



这里要特别注意,你需要修改的class文件是用那个版本的java编译出来的,如果是java5.0,那你重新编译之后也得是java5.0,如果你用了java8.0来编译,那么生成的.class文件就会有可能没法和其他的.class文件一起工作。

这里,Intellij很智能的告诉了我们对应的版本。当然你也可以通过javap这个工具:

Linux:
javap -verbose MyClass | grep "major"
Windows:
javap -verbose MyClass | findstr "major"


你会看到类似的返回:

major version: 50

然后查下表:

Java 1.2 uses major version 46

Java 1.3 uses major version 47

Java 1.4 uses major version 48

Java 5 uses major version 49

Java 6 uses major version 50

Java 7 uses major version 51

Java 8 uses major version 52

第二步,生成java文件

把之前反编译出来的内容简单拷贝一下,然后新建一个maven的工程,在工程下创建对应的java文件,把内容黏贴进去:



这里,我新建了一个BaseDeployer.java的文件。

这时,你看到的情况一定不是像我的截图那样完美,你应该看到一堆红色的警告,因为你得解决依赖!

第三步,解决依赖

通过IDE,查看缺哪些文件:



对应缺少的class,到你的应用服务器上找!

虽然下图中,应用服务器在我的本地机器上,但不妨碍,类似的方法可以在任何地方用,关键是你能找到那些jar包(如果连jar你都拿不到,略过,别看这篇文章了)。可能你要问,为什么要在应用服务器上去找啊。因为只有应用服务上已经部署好的文件,才是真正的,版本匹配的对应的依赖文件。缺少依赖的情况下谈论修改重编译没有意义。

记得选上“Search in Archives”。应该windows的查找工具也能这样吧。同时还得感谢java的设计,类名和文件名是一样的。



这里需要注意的是,你会找到很多同名的类,这时你得用你的脑子想想,哪个是正确的。

找到对应的jar之后,加入到工程中:

<dependency>
<groupId>com.liferay.portal</groupId>
<artifactId>portal-service</artifactId>
<version>1.0.0</version>
<scope>system</scope>
<systemPath>d:/userdata/j18li/.m2/repository/com/liferay/portal/portal-kernel/5.2.3/portal-service.jar</systemPath>
</dependency>


把本地文件作为依赖加到maven,这个东西的关键是在:

<scope>system</scope>和<systemPath></systemPath>
。其他的groupId和artifactId随便填。

第四步,修改,编译并替换

解决完所有的编译,你会看到我上上副帖图的样子。所以的依赖解决了,然后阅读代码,按照你的想法修改这个java文件吧。

然后编译。生成.class文件。这时,要记得第一步的时候提到的,你需要在相同的java version下编译,通过IDE选择对应的version,并设置:



找到包含这个.class文件的jar包。7z打开;

右键->编辑

把你的class文件的内容,替换到打开的notepad文件的内容

保存



然后7zip会帮你更新Jar包

然后重新部署,你会看到你想要的结果。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐