Month: December 2011

Maven的Snapshot版本与Release版本

1. Snapshot版本代表不稳定、尚处于开发中的版本 2. Release版本则代表稳定的版本 3. 什么情况下该用SNAPSHOT?      协同开发时,如果A依赖构件B,由于B会更新,B应该使用SNAPSHOT来标识自己。这种做法的必要性可以反证如下:       a.如果B不用SNAPSHOT,而是每次更新后都使用一个稳定的版本,那版本号就会升得太快,每天一升甚至每个小时一升,这就是对版本号的滥用。       b.如果B不用SNAPSHOT, 但一直使用一个单一的Release版本号,那当B更新后,A可能并不会接受到更新。因为A所使用的repository一般不会频繁更新release版本的缓存(即本地repository),所以B以不换版本号的方式更新后,A在拿B时发现本地已有这个版本,就不会去远程Repository下载最新的B 4. 不用Release版本,在所有地方都用SNAPSHOT版本行不行?           不行。 正式环境中不得使用snapshot版本的库。 比如说,今天你依赖某个snapshot版本的第三方库成功构建了自己的应用,明天再构建时可能就会失败,因为今晚第三方可能已经更新了它的snapshot库。你再次构建时,Maven会去远程repository下载snapshot的最新版本,你构建时用的库就是新的jar文件了,这时正确性就很难保证了。

个人必装软件和必须做的设置

同时使用Ubuntu和Windows: 1.Ubuntu下的五笔字型, Windows下的极点五笔 2.Firefox的插件:   a.Autoproxy   b.Firebug   c.HttpFox   d.Remove Cookies 4.Windows下的7zip 5.Windows下的staruml 6.Ubuntu下的gSTM + Firefox Autoproxy 插件 6.1 设置你的vps的SSH超时时间:     vi /etc/ssh/sshd_config   ClientAliveInterval 60   ClientAliveCountMax 1440 7.Ubuntu下的jdk下载安装及环境变量配置 8.Ubuntu下的chrome 9.Ubuntu下的defuse或meld 10. Ubuntu下的fqterm 11.用VNC让Ubuntu和Windows互联   a.Ubuntu设置好“允许远程登录”,再安装RDSC用作VNC Client   b.Windows下安装UltraVNC,包括Client和Server   c.windows下安装Insomnia,让windows无法休眠,也就让windows上的vnc server无法休眠 12.用FreeNX从Windows连Ubuntu   a.Ubuntu安装FreeNX服务端,可参照Ubuntu官网上的教程   b.Windows安装FreeNX客户端,连接时打开所有能够提高性能的选项,并将连接所需的缓存设高一点 13.Ubuntu下的gnome-connection-manager, 相当于windows下的secureCRT。注意可以用ctrl + shift +c …

个人必装软件和必须做的设置 Read More »

用VNC和Freenx连ubuntu的详细情况

配置:Server在ubuntu, Client在windows. VNC 1.若Ubuntu用户已登录,从windows连接可以成功 2.若Ubuntu用户登录后锁屏,从windows连接可以成功 3.若Ubuntu用户登录后选择“休眠”、“挂起”或“注销”,从windows无法连接 4.Ubuntu用户登录后并且操作人从windows连接成功后,若Ubuntu切换用户,原有的windows连接将断开,试图重连也会失败;但可以使用另一个VNC地址(同一IP:1)来连,连好后看到的将是Ubuntu当前用户的界面 上述现象只所以发生,是因为 VNC只是把当前Ubuntu中当前登录用户能看到的东西共享给windows而已 FreeNX 只要Ubuntu开机了,从windows用FreeNX连Ubuntu就能成功,不管当时的Ubuntu有没有人登录,也不管当时有谁登录了; 从windows登录后,用户会感觉自己开机打开了Ubuntu,不会看到已打开的程序,即使相同的登录名已经登录了 这是 因为FreeNX完全基于SSH,每次登录都相当于开了一个新会话 不过,用FreeNX明显慢于VNC(如果你用的软件是UltraVNC的话) 适用场景:    1.Ubuntu不休眠、注销,那用VNC就够了    2.如果远程的Ubuntu被人休眠、注销、重启了,那就再用FreeNX连上去

谁加载了我 – 2.Tomcat6里面的web应用

public class MyServlet extends HttpServlet { protected void doGet(HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException { print(Servlet.class.getClassLoader()); //输出org.apache.catalina.loader.StandardClassLoader,它负责加载/common下的类库; Servlet.class就是common/servlet-api.jar里的类 print(HttpServlet.class.getClassLoader()); //同上 //看看它的父加载器 print(HttpServlet.class.getClassLoader().getParent()); //是sun.misc.Launcher$AppClassLoader,即system classloader print(MyServlet.class.getClassLoader());//输出org.apache.catalina.loader.WebappClassLoader,它负责加载当前web-app下的类库; MyServlet.class就是当前web-app下的类 //看看它的父加载器 print(MyServlet.class.getClassLoader().getParent()); //输出 org.apache.catalina.loader.StandardClassLoader //试着找一下 Tomcat启动入口类的加载器 print(this.getClass().getClassLoader().loadClass("org.apache.catalina.startup.Bootstrap").getClassLoader()); //输出sun.misc.Launcher$AppClassLoader,即system classloader //看看当前的context class loader是哪个 print(Thread.currentThread().getContextClassLoader()); //输出org.apache.catalina.loader.WebappClassLoader,即加载当前web-app的加载器 } }

谁加载了我 – 1.普通的Main程序

在普通的Main程序中, 某个类是被哪个加载器所加载的? print(String.class.getClassLoader()); //打印null, 这在HotSpot里代表Bootstrap ClassLoader,它负责加载$JAVA_HOME/lib里的类库 print(List.class.getClassLoader()); // 同上 print(learn.classloader.WhoLoadsMe.class.getClassLoader()); // 打印sun.misc.Launcher$AppClassLoader,它在HotSpot里代表System Class Loader, 负责加载用户类路径上的类库 print(learn.classloader.Friend.class.getClassLoader()); //同上 //看看sun.misc.Launcher$AppClassLoader的父加载器和祖父加载器是哪些 print(learn.classloader.Friend.class.getClassLoader().getParent()); //打印sun.misc.Launcher$ExtClassLoader,它在HotSpot里用于加载$JAVA_HOME/lib/ext下的类库 print(learn.classloader.Friend.class.getClassLoader().getParent().getParent()); //打印null, 即Bootstrap ClassLoader Class<?> remoteFriendClass = new learn.classloader.RemoteClassLoader().loadClass( "learn.classloader.RemoteFriend"); print(remoteFriendClass.getClassLoader()); //打印 learn.classloader.RemoteClassLoader,即自写的class loader(后文有这个class loader的代码) //看看自写加载器的父加载器是哪个 print(remoteFriendClass.getClassLoader().getParent()); //打印sun.misc.Launcher$AppClassLoader,即System ClassLoader print(remoteFriendClass.getField("friendOfFriend").getType() .getClassLoader()); //同上, 这意味着在"RemoteFriend"里直接引用的类(后文附上了代码描述这个引用)是由RemoteFriend的加载器所加载的 //最后看下context class loader print(Thread.currentThread().getContextClassLoader()); //打印sun.misc.Launcher$AppClassLoader,即system classloader 附: RemoteClassLoader package learn.classloader; public class …

谁加载了我 – 1.普通的Main程序 Read More »

一步一步地理解Visitor模式

现在能找到的Visitor模式的讲解大都非常跳跃,问题列出来出后,讲着讲着就突然给出了生涩的UML类图和accept()、visit()等奇怪的方法名,让人非常费解; 读者即使理解了,也有囫囵吞枣的感觉,不能领会其精妙之处。 本文试图以问题为驱动,以代码重构的方式,展示我们是怎么样一步一步地解决问题,并选择visitor模式作为重构的终点。 #1.问题域   visitor模式用于遍历一群对象,这些对象按某种结构组织在一起(List, Set, Tree等)。这种场景常常面临的问题是:    组织里的对象的类型彼此不同,遍历者要根据不同的类型使用不同的逻辑,导致代码里频繁使用if语句,可读性、可维护性都会比较差 //这个方法逐个打印每个Employee的称谓 private static void printTitle(Team team) { //一个Team里面的Employee有两种类型:Manager, 或Worker for (Employee employee : team.getEmployees()) { if (employee instanceof Manager) { System.out.println("Manager " + employee.getName()); } if (employee instanceof Worker) { System.out.println("Worker " + employee.getName()); } } }     代码详见 https://github.com/chenjianjx/learn-visitor-pattern/blob/master/1st-PlainSolution/src/learn/visitor/research/client/EmployeeClient.java   要消除if,最常见的方式就是把各个if里面的逻辑塞入到对象的各个子类中 #2.通过多态解决对象类型不同的问题 public class …

一步一步地理解Visitor模式 Read More »

git入门

为什么要用git?     1. svn之类的"Centralized Version Control Systems"有什么问题?      a.服务器的单点问题。服务器一旦当机,所有人都无法提交改动了。      b.如果服务器硬盘坏了,而又没有备机,那你将损失所有revision history     2. git之类的"Distributed version control system" 如何解决上述问题?      客户端存有的文件并不仅仅是最新版本,而是整个repository的镜像。每次checkout都是一次完整的复制。       a.如果服务器硬盘坏了,可以根据客户端的文件恢复       b.由于你镜像了整个repository,所以很多操作都只需在本地完成,速度很快; 而且如果服务器连不上,照样可以看revision history      基本概念   1. git的三种状态     a.committed  — 修改已存入本地数据库     b.modified   — 文件被修改,但还没有提交到本地库     c.staged     — 文件被修改,并且已经被你标识了“将要”进库 ?   2. 几种文件/目录的定义     a. Git directory — 相当于svn的repository目录,用于存放元数据;既然git是"distributed", 所以你的本地和服务器上都会有这个目录。 …

git入门 Read More »

用java attach api + java instrument api写java agent的注意事项

用java attach api + java instrument api写java agent的注意事项 1. 字节码的transformation一旦发生,就会一直生效;agent的detach或中止,并不会使transformation回滚。 2. 由于#1,对于一个目标进程,在允许retransform的条件下,如果先后两次启动agent,就会导致两次transformation的效果叠加起来。举例来说,如果你的transform是在某方法里插入一条日志语句,那如果你先后两次使用你的agent,就会导致被transform的类在执行时生成两条日志。 待续…..

jip和btrace分别是怎么暴露进程数据的?

jip 和 btrace 是两个著名的开源工具,它们都可以察看另一个jvm进程的信息:jip的客户进程可以打印另一个进程中每个方法的执行时间,btrace则可以直接查看甚至改变变量的值。 两个工具可以做的事都直接依赖java instrument api。通过这个api在目标进程运行时修改字节码,在一定程度上改变代码的执行:jip让目标进程给出执行时间,btrace让目标进程给出变量的值。 jip和btrace在执行时都有自己的进程。它们自己的进程接收目标进程释放的信息,然后展现出来。 现在的问题是,工具自己的进程是怎么样跟目标进程通信的? 经研究发现:   1. jip进程与目标进程是通过原生的socket进行通信的。目标进程在启动时须使用-javaagent jip-xxx.jar这个jvm参数(java instrument的“Command-Line Interface”)立即进行字节码instrument操作。具体的操作中包含一步:启动一个ServerSocket. jip进程启动后再访问这个ServerSocket.   2. btrace进程与目标进程则是通过java attach api进行通信的。通过指定一个进程号,btrace进程可以拿到目标进程的句柄。这个句柄是VirtualMachine类的实例,而这个类有一个方法叫loadAgent(),通过这个方法,btrace进程再把预先准备好的agent注入到目标进程实现字节码的动态修改(java instrument的"Starting Agents After VM Startup"模式) 优劣性比较   假设目标进程是java web应用,两者的优劣点可以从多个方面来比较。     1. 运行时的侵入性:btrace优于jip. jip需要在启动目标进程时就使用-javaagent参数,这可能导致贵公司服务器的启动脚本的改动。你们的运维人员未必愿意帮忙。     2. 能否instrument远程的进程:jip优于btrace,因为btrace所基于的java attach api只能捆绑本机的进程,而jip基于的socket没有这个限制。     3. 实现的简易性:btrace优于jip. 使用现成的attach api,当然比手工实现一套基于socket的c/s模型要省事。     4. 平台无关性: jip胜出,因为btrace基于的attach api有两大制约:        a. java6 以后才有这个api        …

jip和btrace分别是怎么暴露进程数据的? Read More »

PMBOK 学习笔记 3.7 项目风险管理

项目风险管理    风险源于不确定性。   风险管理的基本步骤: 识别风险 => 分析风险 => 规划应对方案 第0步: 制定风险管理计划,即 为整个风险管理制定方法论。包括:       a.风险概率的定义:如规定“发生概率超过70%的风险为高可能性风险”       b.风险影响的定义:如规定“二级风险指使进度拖延10%-20%的风险”       c.风险管理活动将占用的时间和资金 第1步: 识别风险       a.项目成员应该参与识别过程,这样可以提高大家的责任感      b.进行识别时可以对照以前项目总结出来的风险checklist       c. 识别出的风险应成文归档,放在“风险登记册”中       d.项目进展过程中可能冒出新的风险,因此“识别风险”是一个持续的过程 第2步: 实施定性风险分析: 分析出风险的发生概率和影响,并排定风险的优先级 第3步: 实施定量风险分析(没看懂,略过)    第4步: 规划风险应对     a.规避风险:如延长进度,缩小范围,使风险消失     b.转移风险:把属于自己的风险转移到别人头上,如让甲方为超支的预算买单。     c.减轻风险:降低风险发生的概率(比如测试做得好一点),或者减少它的影响(比如增加备机)     d.接受风险:付出风险发生的代价,或者准备好B计划 第N/A步: 监控风险      跟踪已识别风险,监测残余风险,识别新风险。这是一个持续进行的过程