在没有源码的情况下修改.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%的进度,我放弃,我就尝试在没有源码的情况下打开吧)
![](http://img.blog.csdn.net/20160825120155017)
这里要特别注意,你需要修改的class文件是用那个版本的java编译出来的,如果是java5.0,那你重新编译之后也得是java5.0,如果你用了java8.0来编译,那么生成的.class文件就会有可能没法和其他的.class文件一起工作。
这里,Intellij很智能的告诉了我们对应的版本。当然你也可以通过javap这个工具:
你会看到类似的返回:
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
![](http://img.blog.csdn.net/20160825121027230)
这里,我新建了一个BaseDeployer.java的文件。
这时,你看到的情况一定不是像我的截图那样完美,你应该看到一堆红色的警告,因为你得解决依赖!
![](http://img.blog.csdn.net/20160825121400296)
对应缺少的class,到你的应用服务器上找!
虽然下图中,应用服务器在我的本地机器上,但不妨碍,类似的方法可以在任何地方用,关键是你能找到那些jar包(如果连jar你都拿不到,略过,别看这篇文章了)。可能你要问,为什么要在应用服务器上去找啊。因为只有应用服务上已经部署好的文件,才是真正的,版本匹配的对应的依赖文件。缺少依赖的情况下谈论修改重编译没有意义。
记得选上“Search in Archives”。应该windows的查找工具也能这样吧。同时还得感谢java的设计,类名和文件名是一样的。
![](http://img.blog.csdn.net/20160825121546445)
这里需要注意的是,你会找到很多同名的类,这时你得用你的脑子想想,哪个是正确的。
找到对应的jar之后,加入到工程中:
把本地文件作为依赖加到maven,这个东西的关键是在:
然后编译。生成.class文件。这时,要记得第一步的时候提到的,你需要在相同的java version下编译,通过IDE选择对应的version,并设置:
![](http://img.blog.csdn.net/20160825135700468)
找到包含这个.class文件的jar包。7z打开;
右键->编辑
把你的class文件的内容,替换到打开的notepad文件的内容
保存
![](http://img.blog.csdn.net/20160825122309372)
然后7zip会帮你更新Jar包
然后重新部署,你会看到你想要的结果。
类似的经历不知是否是常见的情况,总之说说的我的问题:
先发发牢骚,诺记这个公司现在越来越差其实是有原因的,网上很多文章的分析,都有各方面的道理。但在我看来,其中一个原因就是在技术上的迟缓,固步自封,瞻前顾后:
怎么讲,如果要用一个稍微新一点的框架,比如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包
然后重新部署,你会看到你想要的结果。
相关文章推荐
- 在MyEclipse中直接查看class文件(在没有源码的情况下)
- 在没有源码的情况下,在MyEclipse中直接查看class文件
- Eclipse中查看没有源码的Class文件的方法
- [添加用户]解决useradd 用户后没有添加用户Home目录的情况,Linux改变文件或目录的访问权限命令,linux修改用户密码,usermod的ysuum安装包。飞
- Eclipse中查看没有源码的Class文件的方法
- Eclipse中查看没有源码的Class文件的方法——jadclipse插件使用
- 修改了java程序,tomcat中对应的class文件没有更新
- swf格式文件如何修改里面的动作路径或者动作脚本(没有源文件的情况)
- 解决useradd 用户后没有添加用户Home目录的情况,Linux改变文件或目录的访问权限命令,linux修改用户密码
- Eclipse中查看没有源码的Class文件的方法
- [添加用户]解决useradd 用户后没有添加用户Home目录的情况,Linux改变文件或目录的访问权限命令,linux修改用户密码
- 执行ant构建文件过后,没有修改任何相关的文件,第二遍执行ant,这时ant会提示任务已经完成的任务不再执行,记住这是任务级别的,这种情况包括在控制台上指定两个project
- 修改文件权限后,put_content_file提示没有权限
- Discuz!NT源码文件打开时乱码的情况
- SQL Server 数据格式修改时,没有保存按钮的情况解决
- 在没有备份情况下误删除数据文件的恢复
- 如何debug没有源代码的class文件—eclipse+jad
- 发布服务器上IIS修改web.config文件,提示没有权限。
- 拥有所有归档文件,但没有备份情况下的数据文件恢复
- 拥有所有归档文件,但没有备份情况下的数据文件恢复