对于需要查看Java Class文件源码的筒子们来说,必须在项目中导入Java源码才能查看Class文件的具体实现,这不仅十分的麻烦,因为有时我们并不可以获得Class文件对应的Java源码。今天就给大家介绍一款反编译Class文件的工具,有了它,可以查看任何Class文件的源码。
1.下载MyEclipse反编译Class文件的工具工具的下载地址:http://download.csdn.net/detail/yulei_qq/5543635
2.工具的安装
下载后上面的工具之后,解压出来,我们可以看到有两个文件:jad.exe、net.sf.jadclipse_3.3.0.jar 。
第一步:我们将jad.exe文件放到JDK的bin目录下,具体的可以查看下面的图片:
第二步:将 net.sf.jadclipse_3.3.0.jar 拷贝到 MyEclipse安装目录下的plugins目录下面(接下来的步骤我会以我的计算机路径为例子说明)路径在:D:\Users\Administrator\AppData\Local\Genuitec\Common\plugins.具体文件位置见下图:
第三步:在D:\Users\Administrator\AppData\Local\Genuitec\MyEclipse-8.6\dropins创建一个eclipse文件夹.
第四步:在创建好的eclipse文件夹下,分别创建featues、plugins两个文件夹.
第六步:将net.sf.jadclipse_3.3.0.jar 文件分别拷贝到创建好的featues、plugins两个文件夹里面.
第七步:重新启动MyEclipse,在Windows——>Perference——>Java下面应该会多出一个JadClipse目录. 如果没有出现的话,多试几次就OK了,我当时也是这样.
第八步:点击JadClipse,在右边的窗口中配置JadClipse. 设置path to decompiler为jad.exe的全路径,如:C:\jdk\bin\jad.exe,在Directory for temporary files中指定l临时文件路径,如 :D:\Users\Administrator\AppData\Local\Genuitec\MyEclipse-8.6\result ,其中result是新建一个文件夹. 同时需要选中 User Eclipse code formatter ,这样编译出来的Java 代码会和Class文件的格式一样.
为了避免编译后的中文乱码问题,我们需要配置Misc,选中如下单选框.
第九步:安装完成之后,双击Class文件,MyEclipse就自动反编译了.如果没有出现想要的结果,需要检查一下“*.class”默认关联的编辑器为“JadClipse Class File Viewer“ ,具体的操作还是看图吧:
关联之后,就可以自动的反编译啦!
HDFS是一个具有高度容错性的分布式文件系统,适合部署在廉价的机器上,它具有以下几个特点:
1)适合存储非常大的文件
2)适合流式数据读取,即适合“只写一次,读多次”的数据处理模式
3)适合部署在廉价的机器上
但HDFS不适合以下场景(任何东西都要分两面看,只有适合自己业务的技术才是真正的好技术):
1)不适合存储大量的小文件,因为受Namenode内存大小限制
2)不适合实时数据读取,高吞吐量和实时性是相悖的,HDFS选择前者
3)不适合需要经常修改数据的场景
HDFS的架构如上图所示,总体上采用了Master/Slave的架构,主要有以下4个部分组成:
1、Client
2、NameNode
整个HDFS集群只有一个NameNode,它存储整个集群文件分别的元数据信息。这些信息以fsimage和editlog两个文件存储在本地磁盘,Client通过这些元数据信息可以找到相应的文件。此外,NameNode还负责监控DataNode的健康情况,一旦发现DataNode异常,就将其踢出,并拷贝其上数据至其它DataNode。
3、Secondary NameNode
Secondary NameNode负责定期合并NameNode的fsimage和editlog。这里特别注意,它不是NameNode的热备,所以NameNode依然是Single Point of Failure。它存在的主要目的是为了分担一部分NameNode的工作(特别是消耗内存的工作,因为内存资源对NameNode来说非常珍贵)。
4、DataNode
DataNode负责数据的实际存储。当一个文件上传至HDFS集群时,它以Block为基本单位分布在各个DataNode中,同时,为了保证数据的可靠性,每个Block会同时写入多个DataNode中(默认为3)
想了解MapReduce的架构设计,可以参考另外一篇文章介绍MapReduce架构:http://blog.csdn.net/u010415792/article/details/9056129
备忘录,其实名字也比较形象。
我们经常遇到将一个类的状态恢复到历史版本的需求。比如一个记事本,想保存一个上N个状态,通过Ctrl+Z可以恢复此前编辑内容。备忘录就非常适合这种场景。此时发起者类,希望能够将自身状态保留在某处,而且不希望过多的暴露细节。为了上述目的,发起者会在某个时刻通过new出一个备忘类对象,并将该对象托管给管理者类。然后需要恢复状态时,又从管理者类中获取具体状态,将自身恢复到某个状态。
为了保持封装性,备忘录一般除了将自己暴露给发起者外(或者可以认为是发起者将自己状态暴露给了备忘类),不为外部类提供任何访问状态相关接口。C++中这个通常是通过将自己所有接口都改成private(包括构造函数),然后将发起者设为自己的友元类来实现。
写了个demo,可以支持多个版本:
/*************************************************************************** * * Copyright (c) 2013 itegel.com, Inc. All Rights Reserved * **************************************************************************/ /** * @file test_memento.cpp * @author itegel * @date 2013/06/08 11:29:08 * @brief * **/ #include <string> #include <map> #include <iostream> using namespace std; class State{ public: int version; string content; }; class Memento{ public: private: friend class NoteBook; Memento(State state) : _state(state){} ~Memento(){} State * GetState(){ return &_state; } void SetState(State state){ _state = state; } State _state; }; //originator class NoteBook{ public: NoteBook(int version, string content){ _state.version = version; _state.content = content; } NoteBook(State & state):_state(state){ } void SetMemento(Memento * mem){ _state = mem->_state; } Memento * GetMemento(){ return new Memento(_state); } void SetState(int version, string content){ _state.version = version; _state.content = content; } int GetVersion(){ return _state.version; } void PrintState(){ cout<<"Note:\n\tversion:\t"<<_state.version<<endl<<"\tcontent:\t"<<_state.content<<endl; } private: State _state; }; class CareTaker{ public: CareTaker(){} void Save(int id, Memento * mem){ _memento_map[id] = mem; } Memento * GetMemento(int id){ return _memento_map[id]; } private: map<int, Memento *> _memento_map; }; int main(){ NoteBook my_note(0, ""); CareTaker care_taker; my_note.PrintState(); cout<<"Save State 0!"<<endl; care_taker.Save(my_note.GetVersion(), my_note.GetMemento()); cout<<endl<<"Edit for 1st time!"<<endl; my_note.SetState(1, "Hello world!"); my_note.PrintState(); care_taker.Save(my_note.GetVersion(), my_note.GetMemento()); cout<<endl<<"Edit for 2nd time!"<<endl; my_note.SetState(2, "Hello World! It is the 2nd version!"); my_note.PrintState(); care_taker.Save(my_note.GetVersion(), my_note.GetMemento()); cout<<endl<<"Edit for 3rd time!"<<endl; my_note.SetState(3, "Hello Itegel! It is the 3rd version!"); my_note.PrintState(); care_taker.Save(my_note.GetVersion(), my_note.GetMemento()); cout<<endl<<"Restore 2nd version:"<<endl; Memento * mem = care_taker.GetMemento(2); my_note.SetMemento(mem); my_note.PrintState(); cout<<endl<<"Restore 0 version:"<<endl; mem = care_taker.GetMemento(0); my_note.SetMemento(mem); my_note.PrintState(); return 0; }
执行结果:
Note: version: 0 content: Save State 0! Edit for 1st time! Note: version: 1 content: Hello world! Edit for 2nd time! Note: version: 2 content: Hello World! It is the 2nd version! Edit for 3rd time! Note: version: 3 content: Hello Itegel! It is the 3rd version! Restore 2nd version: Note: version: 2 content: Hello World! It is the 2nd version! Restore 0 version: Note: version: 0 content:
备忘录模式使用场景应该比较固定,但是其实现可以很灵活。主要思想就是将自己的状态托管给一个其他类,但是又不想过多的暴露自身信息,从而引入了备忘录类。变化的地方应该是状态成员的变化吧。此时只需要修改State类就好,其他其实可以做到不用修改(除了发起者关于这个新增状态信息的维护)。
这些天一直抽空写一些demo,理解还不够深,但是代码都是自己一行一行敲进去的。这样体会会深一些吧。其实很多时候,还是需要跟实际项目结合,理解会更深一些。个人体会是,程序员多写代码才是王道。