.电脑开机出现这个情况 该怎么开机 正常启动动

全国统一热线:400-028-
VPS SERVER
CLOUD HOST
欢迎光临西部数码,我们将竭诚为您提供最优质的服务!
JS可能转向BSD许可?
郁闷啊,从小出名的“懒人”却长期被失眠所困扰,一到晚上就来劲,一见阳光就萎人了,莫非前世是小倩的相好?转载这篇文章,不等于同意作者的观点。作者屁股坐在意图通过垄断知识谋利的企业的板凳上,乱说一气。只是想借这篇文章让各位了解这么一种很有代表性的观点。是不是中国人有绕过限制的本能?哪怕是用于保障自由的限制。个人认为,知识应该由全人类共享,你可以也应该利用知识谋利,但不能为了谋利而阻扰他人容易地获取知识。这是矛盾的吗?另外要指出一点:作者声称BSD、Linux的人才数量与质量都不及瘟得死,这明显是信口雌黄,数量肯定不及,质量却未必,人多势众是不是都是“人材”更是两说。BSD许可“过于宽松”,如果因此而成为企图通过垄断知识而谋利的JS(JS!绝对的JS!)的转移方向的话,唉,悲哀!绝对滴悲哀!
警惕由Linux引发的知识产权纠纷
――对基于开源代码发展我国自主操作系统及软件的思考
[url=JavaScript:alert('')]查看原文[/url]
)//--&科技日报& &&&作者:王凌峰
& &&&日,美国SCO公司向犹他州盐湖郡第三地方法院提起诉讼指控IBM侵犯该公司知识产权,一度要求IBM公司赔偿30亿美元,后来又降低为10亿美元。根据各大媒体公开信息,SCO的指控主要集中在两点,一是IBM自作主张扩大了其最初从AT&T处获得的Unix使用权限,擅自将一部分Unix源代码用于其Linux产品;二是Linux社区未经SCO授权“抄袭”了受保护的Unix源代码。
& & 5月14日,SCO发函给全球1500家大企业,警告使用Linux的用户可能受到起诉。SCO公司近一步要求这些公司为每台Linux服务器支付699美元的使用许可费用。
& & 9月初中日韩就联合开发基于Linux的新操作系统达成共识。
& & 9月11日,新浪科技登载一篇题为“发展Linux将为我国软件业带来麻烦”的文章,一石激起千层浪。
& & 这些前前后后的新闻之间是否存在某种内在联系?对于我国自主开发操作系统的重大战略抉择又有何影响?
& & SCO起诉IBM对于业界来说,远远不是两家公司之间的胜负问题,更重要的含义在于,迫使人们深入思考起诉所揭开的开源代码知识产权问题。
& & 开源代码的知识产权问题
& & 目前有30多种开源软件许可证,如BSD许可证、MIT许可证、APSL(Apple公共源码许可证)、Artistic许可证、Mozilla公共许可证、GPL公共许可证和它的变形形式LGPL,以及一些不太为人知的许可证如:Java社区源码许可证和IBMXML4J评估和商业许可证、SPL(Sun公共许可证)等。不同许可证对于软件代码使用、发行到权益归属等的规定有着实质性差异。因此,企业要仔细区别不同许可证之间的区别,以避免可能的知识产权纠纷。
& & 形形色色的开源软件许可证中,最为人们熟知的是GPL许可证。目前开源软件授权所采用的许可证,高达50.36%遵循GPL许可证规则发行。Linux也是依照GPL发布的。
& & GPL许可证是开放源代码软件领域最富盛名的一种许可证,但同时也是开放源代码软件领域对使用者权利限制最严的。GPL承认著作者版权,但要求作者开放源代码和提供免费下载,让其他用户自由使用。即由GPL软件“派生”出的作品也必须遵循GPL。除非能够证明再发布作品的某一部分并非是程序的修改或其衍生作品,而是独立的部分,则形成“不同作品”。不同作品独立发布时,不受GPL条款的约束,作者对该作品享有完整的著作权。但是即使是不同作品,但当它作为衍生作品的一部分发布时,作为一个整体它仍受GPL的约束。也就是说必须公开源代码。
& & 很难想象,一个用户会为一个可以在网上可以自由下载代码的软件支付大笔费用。因此GPL不啻是用户的天堂而是厂商的地狱。如果国内对开源软件的许可规则缺乏深入理解,继续基于遵循GPL许可证的开源代码进行研发,尤其是基于Linux进行操作系统等基础软件研发,势必将埋下严重的知识产权隐患。目前国内Linux厂商几乎无人开放源代码,事实上已经违反了GPL协议,只是目前还没有遭到Linux核心作者的起诉而已。他们对Linux的好处喋喋不休,但对GPL协议的知识产权含义却顾左右而言其他。
版权申明:本站文章均来自网络,如有侵权,请联系028-0
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。
服务器技术
西部数码.cn
CopyRight & &西部数码&版权所有
电话总机:028- (20线)
400电话: 400-科普:你该认识的四种常见开源许可证_网易数码
科普:你该认识的四种常见开源许可证
用微信扫码二维码
分享至好友和朋友圈
(原标题:科普:你该认识的四种常见开源许可证)
第1页:GPL与LGPL开源协议开源早已成为很多科技企业关注的焦点,我们也常会发现部分开源技术后面标注了某种协议,这意味着这些开源代码被框上了某种束缚,或者说这些代码将必须遵循这些规则,否则可能会触及法律。总的来看,如今比较流行的开源软件协议包括:GPL,LGPL,Apache&License(2.0)和BSD。一般来讲,如果使用了GPL许可证的软件,就意味着你的软件必须“自由”,相比之下,其他协议大多只要求使用者尊重原作就可以了,更适用于商业软件之中,只有区分了这些开源软件协议的含义,才能更好的利用和回馈开源软件。你需要了解的开源许可证  GPL(GNU&General&Public&License&Versions)GPL协议一般还可以分为GPL2.0和GPL3.0两种,而GPL3.0是更新一代的开源标准,在对用户专利的保护和DRM的限制方面有所更改。GPL协议同其它的自由软件许可证一样,许可社会公众享有:运行、复制软件的自由,发行传播软件的自由,获得软件源码的自由,改进软件并将自己作出的改进版本向社会发行传播的自由。&而GPL协议就像一种开源“病毒”,任何一款沾染上他的软件都不得不保持开源和免费。GPL许可证根据国外论坛Robbin的解释:“GPL是针对软件源代码的版权,而不是针对软件编译后二进制版本的版权。你有权免费获得软件的源代码,但是你没有权力免费获得软件的二进制发行版本。GPL对软件发行版本唯一的限制就是:你的发行版本必须把完整的源代码一同提供。”  LGPLLGPL是GNU&Lesser&General&Public&License(GNU宽通用公共许可证)的缩写形式,LGPL是GPL的一个为主要为类库使用设计的开源协议。与上面的GPL不同的是,LGPL允许商业软件通过类库引用(link)方式使用LGPL类库而不需要开源商业软件的代码。使采用LGPL协议的开源代码可以被商业软件作为类库引用并发布和销售。我们也可以简单理解为:LGPL协议的开源代码商业软件可以使用,但不能修改LGPL协议的代码。
第2页:Apache License与BSD开源协议  Apache&LicenseApache&Licence是著名的非盈利开源组织Apache采用的协议。该协议和BSD类似,同样鼓励代码共享和尊重原作者的著作权,同样允许代码修改,再发布(作为开源或商业软件)。他需要满足的条件包括:○需要给代码的用户一份Apache&Licence○如果你修改了代码,需要在被修改的文件中说明。○在延伸的代码中(修改和有源代码衍生的代码中)需要带有原来代码中的协议,商标,专利声明和其他原来作者规定需要包含的说明。○如果再发布的产品中包含一个Notice文件,则在Notice文件中需要带有Apache&Licence。你可以在Notice中增加自己的许可,但不可以表现为对Apache&Licence构成更改。  BSD开源协议(Berkerley&Software&Distribution)目前BSD开源协议分为BSD&3-Clause和BSD&2-Clause两种,分别代指两个条款和三个条款的BSD协议。应该说,BSD开源协议是一个给于使用者很大自由的协议。基本上使用者可以自由的使用,修改源代码,也可以将修改后的代码作为开源或者专有软件再发布。但是,不可以用开源代码的作者/机构名字和原来产品的名字做市场推广。这就不难理解,很多的公司企业在选用开源产品的时候都首选BSD协议,因为可以完全控制这些第三方的代码,在必要的时候可以修改或者二次开发。 除了上面的集中开源协议,还有MIT许可证(源自麻省理工,是与BSD一样宽范的许可协议)和Mozilla许可证等,具体可参照下图。
开源许可证(图片来自:阮一峰blog)
本文来源:中关村在线
责任编辑:王晓易_NE0011
用微信扫码二维码
分享至好友和朋友圈
加载更多新闻
热门产品:   
:        
:         
热门影院:
阅读下一篇
用微信扫描二维码
分享至好友和朋友圈Select&*&from&&table1&A&where&A.col1&not&in&(&select&col1&from&table2&B&)
如果这样,本来应该有一条数据,结果没有。
如果我改写成这样:
select&*&from table1 A where&not&exists&(SELECT * FROM table2 B where B.col1 = A.col1)
结果就正确,有一条数据显示。
经过一番搜索,原以为是子查询结果集太大的原因。
后来有网上强人指点:子查询里面有空集。即子查询的结果集里面有NULL的结果。
把查询语句修改成:
Select&*&from&&table1&A&where&A.col1&not&in&(&select&col1&from&table2&B&where&B.col1&is&not&null&)
果然就查出来了。而且一点不差。。。厉害阿~~~
下面是针对本文题的分析:
1。 首先来说说Oracle中的NULL。
Oracle中的NULL代表的是无意义,或者没有值。将NULL和其他的值进行逻辑运算,运算过程中,NULL的表现更象是FALSE。
下面请看真值表:
另外,NULL和其他的值进行比较或者算术运算(&、&、=、!=、+、-、*、/),结果仍是NULL。
如果想要判定某个值是否为NULL,可以用IS NULL或者IS NOT NULL。
2. 再来说说Oracle中的IN。
in是一个成员条件, 对于给定的一个集合或者子查询,它会比较每一个成员值。
IN功能上相当于 =ANY 的操作,而NOT IN 功能上相当于 !=ALL 的操作。
IN在逻辑上实际上就是对给定的成员集合或者子查询结果集进行逐条的判定,例如:
SELECT&*&FROM&table1&A&WHERE&A.col1&in&(20,50,NULL);
实际上就是执行了
SELECT&*&FROM&table1&A&WHERE&A.col1=20&OR A.col1=50&OR A.col1=NULL;
这样,根据NULL的运算特点和真值表,我们可以看出,上边这个WHERE 字句可以被简化(如果返回NULL则无结果集返回,这一点和FALSE是一样的)为
WHERE&A.col1=20&OR&A.col1=50
也就是说,如果你的table1中真的存在含有NULL值的col1列,则执行该语句,无法查询出那些值为null的记录。
再来看看NOT IN。根据逻辑运算关系,我们知道,NOT (X=Y OR N=M) 等价于 X!=Y AND N!=M,那么:
SELECT&*&FROM&table1&A&WHERE&A.col1&not&in&(20,50,NULL)
SELECT&*&FROM&table1&A&WHERE&A.col1!=20&AND&A.col1!=50&AND&A.col1!=NULL
根据NULL的运算特性和真值表,该语句无论前两个判定条件是否为真,其结果一定是NULL或者FALSE。故绝对没有任何记录可以返回。
这就是为什么语句1查不到应有结果的原因。当然,如果你用NOT IN的时候,预先在子查询里把NULL去掉的话,那就没问题了,例如语句3。
有些童鞋可能要问了:那如果我想把A表里面那些和B表一样col1列的值一样的记录都查出来,即便A、B两表里面的col1列都包括值为NULL的记录的话,用这一条语句就没办法了吗?
我只能很遗憾的告诉你,如果你想在WHERE后面单纯用IN 似乎不太可能了,当然,你可以在外部的查询语句中将NULL条件并列进去,例如:
SELECT&*&FROM&table1&A&WHERE&A.col1&in&(SELECT&B.col1&FROM&table2&B)&OR&A.col1&IS&NULL;
3. 最后谈谈EXISTS。
有人说EXISTS的性能比IN要好。但这是很片面的。我们来看看EXISTS的执行过程:
select&*&from&t1&where&exists&(&select * from&t2&where t2.col1 = t1.col1 )
for&x&in&(&select&*&from&t1&)
&&&&&&if&(&exists&(&select * from&t2&where t2.col1 =&x.col1 )
&&&&&&then
&&&&&&&&&OUTPUT&THE&RECORD in x
&&&&&&end&if
也就是说,EXISTS语句实际上是通过循环外部查询的结果集,来过滤出符合子查询标准的结果集。于是外部查询的结果集数量对该语句执行性能影响最大,故如果外部查询的结果集数量庞大,用EXISTS语句的性能也不一定就会好很多。
当然,有人说NOT IN是对外部查询和子查询都做了全表扫描,如果有索引的话,还用不上索引,但是NOT EXISTS是做连接查询,所以,如果连接查询的两列都做了索引,性能会有一定的提升。
当然至于实际的查询效率,我想还是具体情况具体分析吧。
那么我们不妨来分析一下语句2为什么能够的到正确的结果吧:
语句2是这样的:
select&*&from table1 A where&not&exists&(SELECT B.col1 FROM table2 B where B.col1 = A.col1)
实际上是这样的执行过程:
for&x&in&(&select&*&from table1 A )
&&&&&&if&(not exists&(&select * from table2 B where B.col1 =&x.col1 )
&&&&&&then
&&&&&&&&&OUTPUT&THE&RECORD in x
&&&&&&end&if
由于表A中不包含NULL的记录,所以,遍历完表A,也只能挑出表A中独有的记录。
这就是为什么语句2能够完成语句3的任务的原因。
但如果表A中存在NULL记录而表B中不存在呢?
这个问题请大家自己分析吧。哈哈。有答案了可以给我留言哦。
答案:A表中的NULL也会被查出来。因为select * from table2 B where B.col1 = NULL不返回结果,故
not exists ( select * from table2 B where B.col1 = x.col1 )的值为真。
以上SQL运行结果在MySQL和Oracle上都已经通过。
X-Spirit 阅读(4602) |
想从备份的dmp文件中导入某些表的时候,可以用如下imp命令,格式:
imp username/password@本地net服务名 file=xxx.dmp fromuser=xx touser=xx tables=(tablename)
username:登陆数据库的用户名
password:登陆数据库的密码
本地net服务名:连接服务器的本地net服务名
file:你的dmp文件的路径
fromuser,touser:从一个用户导入到另外一个用户
tables:从dmp文件中导入的表名
X-Spirit 阅读(913) |
一、emacs编辑器简介
emacs编辑器是由C语言和LISP语言编写的。LISP(链表处理语言)是由约翰·麦卡锡在1960年左右创造的一种基于λ演算的函数式编程语言。 我们可以使用LISP来扩展emacs,从而为emacs添加更多的命令。(补:emacs -nw:以命令行的方式来运行emacs,而不启动GUI界面)
* 自动保存功能
如果你已经修改了一个文件,但是还没来得及存盘你的计算机就罢工了,那么你所做的修改就很可能会丢失。为了避免这样的不幸发生,Emacs 会定期将正在编辑的文件写入一个“自动保存”文件中。自动保存文件的文件名的头尾各有一个“#”字符,比如你正在编辑的文件叫“hello.c”,那么它 的自动保存文件就叫“#hello.c#”。这个文件会在正常存盘之后被 Emacs 删除。
所以,假如不幸真的发生了,你大可以从容地打开原来的文件(注意不是自动保存文件)然后输入 M-x recover file&Return& 来恢复你的自动保存文件。在提示确认的时候,输入 yes&Return&。
当emacs失去响应时,C-g命令可用来结束纸条命令的执行。其功能相当于Shell中的Ctrl+C
有一些 Emacs 命令被“禁用”了,以避免初学者在不了解其确切功能的情况下误用而造成麻烦。如果你用到了一个被禁用的命令,Emacs 会显示一个提示消息,告诉你这个命令到底是干什么的,询问你是否要继续,并在得到你的肯定之后再执行这命令
二、emacs编辑器的界面
用来进行文本编辑的区域。
如果 Emacs 发现你输入多字符命令的节奏很慢,它会在窗格的下方称为“回显区”的地方给你提示。回显区位于屏幕的最下面一行。
位于回显区正上方的一行被称为“状态栏”。状态栏最开头的星号(*)表示你已经对文字做过改动。刚刚打开的文件肯定没有被改动过,所以状态栏上显示的不是星号而是短线(-)。
状态栏中的小括号用来指明当前使用的编辑模式,默认是fundamental(主模式),emacs的主模式包括了文本模式以及编辑程序源码的Lisp模式等。
三、emacs所能提供的工作环境
emacs可以执行Shell命令
emacs可以作为Directory Editor(Dired)
emacs可以编辑、编译以及调试程序
emacs可以编辑其它主机上的文档
emacs可以打印文件
emacs具有年历(Calendar)以及日记功能
emacs可以用来阅读man page和info文档
emacs可以收发电子邮件
emacs可以阅读网络上的电子布告栏(GNUS)
emacs具有版本控制的功能(CVS)
emacs可以提供娱乐环境(游戏功能)
emacs所提供的这些功能,都是先唤起代表此功能的模式(mode)。emacs的模式,分成主要模式(major mode)与次要模式(minor mode)。每一次只能使用一个主模式,而且主模式是必须要的。在一个主模式下,俄可以搭配一个以上的次要模式。使用次要模式相当于启用了该次要模式所对应的插件。
四、emacs命令
emacs中的每一个命令都有一个命令名,命令名就是该命令所对应的LISP函数的函数名。在emacs中,我们可以为这些命令配置快捷键,从而达到快速调用命令的目的。
.使用emacs来执行命令的方法有两种:(1).使用Ctrl键 (2).使用Meta键。所有emacs命令都可以用Meta键表示出来,键盘上如果没有Meta键,则可以用Alt键或ESC键来代替。常用的emacs命令通常会有一个快捷键与之相连。快捷键通常是以Ctrl来开头(C-x C-c)。如果要使用Meta键来表达与“Ctrl-x Ctrl-c”相同的效果,则使用“M-x save-buffers-kill-emacs”。使用Meta键,可以利用emacs的completion功能。使用emacs的completion功能的方法是将部分字符串键入后,再按下TAB、SPACE或?键即可。
(1).TAB键:尽可能将其的字填满。
(2).SPACE键:将分隔符(-)之前的字填满。
(3).?:将所有可能的completion选择都列出来。
由于emacs中所有的命令都有一个命令名(LISP函数的函数名),因此,我们可以使用“M-x 命令名”来调用emacs中的所有的命令。
* 基本光标控制
C-v:向下翻屏,与PageDown效果相同(v-& vertical)
M-v:向上翻屏,与PageUp效果相同
C-l:重绘屏幕,并将光标所在行置于屏幕的中央
C-b:光标向前移动一格(b-&backward)
C-f:光标向后移动一格(f-&forward)
C-p:光标向前移动一行(p-&previous)
C-n:光标向后移动一行(n-&next)
M-b:光标向前移动一个单词
M-f:光标向后移动一个单词
C-a:光标移动到行首
C-e:光标移动到行尾
M-&:光标移动到文章的开头(注意:“&”的输入要shift键,实际为Alt+Shift+&)
M-&:光标移动到文章的结尾
C-u:给命令传递参数。例如:“C-u 2 C-d”表示删除两个字符
M-x goto-line n RET:调到第n行
* 编辑命令
C-d:删除光标后的一个字符
C-k:删除从光标到行尾的字符(k-&killl)
C-x u:Undo(想要redo,随便输入一个字符,在Undo)
C-SPC、C-@、M-x set-mark-command:设置mark
C-x h:将整个缓冲区设置为区域
C-w:将区域的文本删除,并放入yanking ring中。区域指的是从mark到point(光标所处的位置称为point)之间的文本
M-w:复制区域到yanking ring中
C-y:将yanking ring中最后一个区域插入当前缓冲区
M-j:回车并且到下一行产生适当的缩进
M-m:将光标移动到当前行的第一个非空白字符上
M-;:产生通用注释
M-x comment-region:把块注释掉
M-x kill-comment:消除注释
* 查找与替换
C-s:向后搜索,光标将停在第一个匹配的字符串处。再按一次C-s将继续搜索下一个匹配的字符串。如果要停止搜索,则使用C-g,此时光标将会回到搜索开始的位置
C-r:向前搜索
M-x replace-string:替换
* 文件操作
C-x c-f:打开文件,如果文件不存在则创建
C-x C-s:保存文件。第一次存盘时,emacs会将文件重命名来备份。重命令的规则通常是在原文件名后加上一个“~”字符。如果要关闭emacs的自动备份功能,使用 M-x customize-variable &Return& make-backup-files &Return&
C-x C-w:将文件“另存为”
C-x C-v:打开一个新文件,并关闭当前缓冲区
C-x C-r:以只读的方式打开文件
C-x i:将文件插入光标当前位置
Emacs 把每个编辑中的文件都放在一个称为“缓冲区(buffer)”的地方。每打开一个文件,Emacs 就在其内部开辟一个缓冲区用来保存打开的文件的数据。ESC ESC ESC命令可以用来退出打开的小缓冲区,比如:命令提示窗格等
列出当前所有的缓冲区(b-&buffer)
C-x b 缓冲区名:切换到指定的缓冲区(例如:C-x b M&tab&:切换到以M开头的缓冲区)
C-x s:保存emacs中所有的缓冲区(s-&save)
C-x right:切换到下一个缓冲区
C-x left:切换到前一个缓冲区
C-x C-c:退出emacs,并询问用户是否保存
C-x k:关闭缓冲区
C-z:将emacs挂起,然后回到Shell中,并不退出emacs。之后,我们可以使用%emacs或fg命令来回到emacs
Emacs 可以有多个窗格,每个窗格显示不同的文字。
C-x 0:关闭光标所在的窗口
C-x 1:保留光标所在的窗格,并将其扩大到整个屏幕,同时关掉所有其它的窗格
C-x 2:水平分割当前窗口
C-x 3:垂直分割当前窗口
C-x o:在emacs的窗格中进行切换(o-&other)
C-M-v:滚动下方的窗格。一般在我们使用下方的窗格进行参考,而又不想将光标切换到下一个窗格时使用
* 使用帮助
C-h c 快捷键:显示快捷键的简要说明
C-h k 快捷键:显示快捷键所对应的命令名及其详细说明
C-h a 关键字:显示包含有指定关键字的命令
C-h i:查看Info文档
* 在emacs中运行shell命令
M-! cmd RET:打开一个名为“*Shell Command Output*“的窗口,并把该命令的执行结果显示在其中。按下”C-x 1“组合键可以关闭这个窗口。由于Shell命令的输出是在一个编辑缓冲区里,因此我们可以对它进行编辑、保存等操作。
M-| cmd RET:运行Shell命令,并使用编辑窗口中选定的区域作为该Shell命令的输入,然后可以选择是否用该Shell命令的输出来替换编辑窗口中选中的区域。
C-u M-! cmd RET:执行一条Shell命令,并将其输出放到编辑区中光标所在的位置处,而不将其输出到”Shell Command Output“窗口。
M-x shell:运行一个子Shell,该子Shell对应于emacs中的一个名为”*Shell*"的缓冲区,此后,我们就可以交互式的运行Shell命令了。
M-x term:运行一个子Shell,该子Shell对应于emacs中的一个名为“*Terminal*”的缓冲区。使用该命令获得的子Shell是一个完整的Shell的模拟,与我们直接在Shell中操作没有什么差别。
M-x eshell:运行emacs shell。该Shell为emacs自己实现的一个shell,而前面运行的shell都为系统中的shell程序(例如:/bin/csh等)。我们可以通过设置变量shell-file-name来设置emacs所使用的默认shell
* Dired功能
emacs的Dired(Directory Editor)功能使emacs缓冲区能够用来显示目录列表,并可以用来进入目录的子目录。Dired缓冲区是只读的,不能够被修改。
C-x d:进入Dired
* emacs配置文件
emacs配置文件通常位于计算机的 $HOME 目录,如果是 MS Windows (Windows 2000, Windows XP以上),默认是 c:\Documents and Settings\username\Application Data\,这个适用于 Emacs22 以上的版本。Emacs21 默认的 $HOME 目录在 C:\ 。当然也可以通过环境变量 $HOME 重新设置,总之在比较大众化的操作系统中,你都可以通过C-x C-f ~/.emacs 来编辑您的个性化配置文件。
;;显示时间
(display-time)
;;显示行号
(column-number-mode t)
(show-paren-mode t)
;;设置TAB宽度为4
(setq default-tab-width 4)
;;以下设置缩进
(setq c-indent-level 4)
(setq c-continued-statement-offset 4)
(setq c-brace-offset -4)
(setq c-argdecl-indent 4)
(setq c-label-offset -4)
(setq c-basic-offset 4)
(global-set-key "\C-m" 'reindent-then-newline-and-indent)
(setq indent-tabs-mode nil)
(setq standard-indent 4)
;;开启语法高亮。
(global-font-lock-mode 1)
;;设置默认工作目录
(setq default-directory "/home/test/source/")
;; 去掉滚动条
(set-scroll-bar-mode nil)
;;关闭开启画面
(setq inhibit-startup-message t)
(setq indent-tabs-mode t)
;;不产生备份文件
(setq make-backup-files nil)
;;设置自定义变量
(custom-set-variables
'(column-number-mode t)
'(current-language-environment "UTF-8")
'(display-time-mode t)
'(ecb-options-version "2.32")
'(mouse-1-click-in-non-selected-windows t)
'(mouse-drag-copy-region t)
'(mouse-yank-at-point t)
'(save-place t nil (saveplace))
'(show-paren-mode t)
'(transient-mark-mode t))
(custom-set-faces
;;选择小工具栏图标
(tool-bar-mode -1)
rectangle(列)模式编辑 和emacs shell(摘抄)
不敢独享,与大家分享。也可以在Emacs中用C-x C-h列出全部命令,查找C-x r c,所有列模式命令都是以C-x r开始的
C-x r C-@&&&&&&&&&&&&&&&&&&& point-to-register
C-x r SPC&&&&&&&&&&&&&&&&&&& point-to-register
C-x r +&&&&&&& increment-register
C-x r b&&&&&&& bookmark-jump
C-x r c&&&&&&& clear-rectangle
先用C-space或者C-@设一个mark,移动光标到另一点,使用C-x r c可以清楚mark到光标处的矩形区域,该区域留下空白。
C-x r d&&&&&&& delete-rectangle
删除矩形区域,不留空白,后面的字符前移
C-x r f&&&&&&& frame-configuration-to-register
C-x r g&&&&&&& insert-register
C-x r i&&&&&&& insert-register
将某个寄存器的内容插入某处
C-x r j&&&&&&& jump-to-register
C-x r k&&&&&&& kill-rectangle
就是剪切某个选定的矩形区域,用C-x r y可以贴上
C-x r l&&&&&&& bookmark-bmenu-list
C-x r m&&&&&&& bookmark-set
C-x r n&&&&&&& number-to-register
C-x r o&&&&&&& open-rectangle
在选定的矩形区域插入空白
C-x r r&&&&&&& copy-rectangle-to-register
将选定的矩形区域复制到某个寄存器
C-x r s&&&&&&& copy-to-register
C-x r t&&&&&&& string-rectangle
在选定区域所有列前插入同样的字符
C-x r w&&&&&&& window-configuration-to-register
C-x r x&&&&&&& copy-to-register
C-x r y&&&&&&& yank-rectangle
类似于矩形区域的粘贴,就是将刚用C-x r k剪切的矩形区域粘贴过来
C-x r C-SPC&&& point-to-register
在 Emacs 里面同时打开多个 shell 会话:
通过重命名shell所在缓冲区的名字可以开启多个shell
E-x rename-buffer shellA
这时就开启了两个不相干的shell:shellA 和*shell*
也可以通过其他方式来开启shell,例如:
1. M-x eshell&&& 开启Emacs Shell
2. M-x term&&&&& 开启linux终端,可以指定你要的终端SHELL。但是这个可能会拦截你的EMACS命令。
整理你的屏幕:
通过C-c C-o可以清除上次命令的输出,特别是对于cat或dmesg这种产生大量输出的命令。
详细文章:
X-Spirit 阅读(693) |
MOZILLA PUBLIC LICENSE
License,允许免费重发布、免费修改,但要求修改后的代码版权归软件的发起者。这种授权维护了商业软件的利益,,它要求基于这种软件得修改无偿贡献
版权给该软件。这样,围绕该软件得所有代码得版权都集中在发起开发人得手中。但MPL是允许修改,无偿使用得。MPL软件对链接没有要求。
BSD开源协议(、、)
BSD开源协议是一个给于使用者很大自由的协议。基本上使用者可以"为所欲为",可以自由的使用,修改源代码,也可以将修改后的代码作为开源或者专有软件再发布。
但"为所欲为"的前提当你发布使用了BSD协议的代码,或则以BSD协议代码为基础做二次开发自己的产品时,需要满足三个条件:
如果再发布的产品中包含源代码,则在源代码中必须带有原来代码中的BSD协议。
如果再发布的只是二进制类库/软件,则需要在类库/软件的文档和版权声明中包含原来代码中的BSD协议。
不可以用开源代码的作者/机构名字和原来产品的名字做市场推广。
代码鼓励代码共享,但需要尊重代码作者的著作权。BSD由于允许使用者修改和重新发布代码,也允许使用或在BSD代码上开发商业软件发布和销售,因此是对
商业集成很友好的协议。而很多的公司企业在选用开源产品的时候都首选BSD协议,因为可以完全控制这些第三方的代码,在必要的时候可以修改或者二次开发。
Apache Licence 2.0(、、)
Apache Licence是著名的非盈利开源组织Apache采用的协议。该协议和BSD类似,同样鼓励代码共享和尊重原作者的著作权,同样允许代码修改,再发布(作为开源或商业软件)。需要满足的条件也和BSD类似:
需要给代码的用户一份Apache Licence
如果你修改了代码,需要再被修改的文件中说明。
在延伸的代码中(修改和有源代码衍生的代码中)需要带有原来代码中的协议,商标,专利声明和其他原来作者规定需要包含的说明。
如果再发布的产品中包含一个Notice文件,则在Notice文件中需要带有Apache Licence。你可以在Notice中增加自己的许可,但不可以表现为对Apache Licence构成更改。
Apache Licence也是对商业应用友好的许可。使用者也可以在需要的时候修改代码来满足需要并作为开源或商业产品发布/销售。
我们很熟悉的Linux就是采用了GPL。GPL协议和BSD, Apache
Licence等鼓励代码重用的许可很不一样。GPL的出发点是代码的开源/免费使用和引用/修改/衍生代码的开源/免费使用,但不允许修改后和衍生的代
码做为闭源的商业软件发布和销售。这也就是为什么我们能用免费的各种linux,包括商业公司的linux和linux上各种各样的由个人,组织,以及商
业软件公司开发的免费软件了。
GPL协议的主要内容是只要在一个软件中使用("使用"指类库引用,修改后的代码或者衍生代
协议的产品,则该软件产品必须也采用GPL协议,既必须也是开源和免费。这就是所谓的"传染性"。GPL协议的产品作为一个单独的产品使用没有任何问题,
还可以享受免费的优势。
由于GPL严格要求使用了GPL类库的软件产品必须使用GPL协议,对于使用GPL协议的开源代码,商业软件或者对代码有保密要求的部门就不适合集成/采用作为类库和二次开发的基础。
其它细节如再发布的时候需要伴随GPL协议等和BSD/Apache等类似。
LGPL是GPL的一个为主要为类库使用设计的开源协议。和GPL要求任何使用/修改/衍生
之GPL类库的的软件必须采用GPL协议不同。LGPL
允许商业软件通过类库引用(link)方式使用LGPL类库而不需要开源商业软件的代码。这使得采用LGPL协议的开源代码可以被商业软件作为类库引用并
发布和销售。
但是如果修改LGPL协议的代码或者衍生,则所有修改的代码,涉及修改部分的额外代码和衍生
的代码都必须采用LGPL协议。因此LGPL协议的开源
代码很适合作为第三方类库被商业软件引用,但不适合希望以LGPL协议代码为基础,通过修改和衍生的方式做二次开发的商业软件采用。
GPL/LGPL都保障原作者的知识产权,避免有人利用开源代码复制并开发类似的产品
MIT是和BSD一样宽范的许可协议,作者只想保留版权,而无任何其他了限制.也就是说,你必须在你的发行版里包含原许可协议的声明,无论你是以二进制发布的还是以源代码发布的.
Public Domain
公共域授权。将软件授权为公共域,这些软件包没有授权协议,任何人都可以随意使用它。
Artistic许可使作者保持对进一步开发的控制。
以下为对GPL协议的进一步解释:
=================================================================================
GNU通用公共许可证(GNU General Public License)(英文通常以GNU GPL或是直接簡短的以GPL表示),是一個廣泛被使用的,最初由为而撰写。此许可证最新版本为“版本3”,发布。(GNU Lesser General Public License,一般簡稱LGPL)是改自GPL的另一個版本,其目的是為了應用於一些軟體函式庫。
GPL給予了電腦程式的定義,並且使用了所謂的""來確保程式的自由被完善的保留。
GPL授予接受人以下权利,或称“自由”:
以任何目的运行此程序的自由;
以学习程序工作机理为目的,对程序进行修改的自由(能得到源代码是前提);
再发行复制件的自由;
改进此程序,并公开发布改进的自由(能得到源代码是前提)
相反地,随版权所有软件的最终用户许可证几乎从不授予用户任何权利(除了使用的权利),甚至可能限制法律允许的行为,比如。
GPL与其他一些更“许可的”自由软件许可证(比如)相比,主要区别就在于GPL寻求确保上述自由能在复制件及中得到保障。它通过一种由斯托曼发明的叫的法律机制实现,即要求GPL程序的演绎作品也要在GPL之下。相反,BSD式的许可证并不禁止演绎作品变成。
由于某些原因,GPL成为了和的最流行许可证。到,GPL已占上所列的自由软件的约75%,的约68%。类似的,一项关于 7.1的调查显示一般的代码都以GPL发布。著名的GPL自由软件包括核心和。
GPL由斯托曼撰写,用于。它以、、的许可证的早期版本为蓝本。这些许可证都包含有一些GPL的版权思想,但仅只针对特定程序。斯托曼的目标就是创造出一种四海之内皆可使用的许可证,这样就能为许多源代码共享计划带来福音。GPL版本1就这样,在诞生。
到时,因为一些而出现了对比GPL更宽松的许可证的需求。所以当GPL版本2在发布时,另一许可证——库通用许可证(Library General Public License,简称LGPL)也随之发布,并记作“版本2”以示对GPL的补充。版本号在LGPL版本2.1发布时不再相同,而LGPL也被重命名为(Lesser General Public License)以体现GNU哲学观。
GPL版本1,即最初的版本,发布于1989年一月,其目的是防止那些阻碍自由软件的行为,
而这些阻碍软件开源的行为主要有两种(一种是软件发布者只发布可执行的二进制代码而不发布具有源代码,一种是软件发布者在软件许可加入限制性条款)。因此
按照GPLv1,如果发布了可执行的二进制代码,就必须同时发布可读的源代码,并且在发布任何基于GPL许可的软件时,不能添加任何限制性的条款。
在GPLv2中所做的最大的改动就是增加了“自由还是死亡”("Liberty or Death")这章条款,即第七章。这章中申明道,如果哪个人在发布源于GPL的软件的时候,同时添加强制的条款,以在一定程度上保障和尊重其它一些人的自由和权益(也就是说在一些国家里,人们只能以二进制代码的形式发布软件,以保护开发软件者的版权),那么他将根本无权发布该软件。
到了,人们普遍认为一个限制性弱的许可证对于自由软件的发展是有战略意义上的好处的;因此,当GPL的第二个版本(GPLv2)在发布时,与此同时第二个许可证程式庫GNU通用公共许可证(LGPL,the Library General Public License )也被发布出来并且一开始就将其版本定为第2版本以表示其和GPLv2的互补性。这个版本一直延续到,并分支出一个衍生的LGPL版本号为2.1,并将其重新命名为轻量级通用公共许可证(又称宽通用公共许可证)(Lesser General Public License)以反应其在整个GNU哲学中的位置。
到,GPL版本3正由斯托曼起草,由和(Software Freedom Law Center)提供法律咨询。
斯托曼在的演讲上说:()
在所有的改动中,最重要的四个是:
解决软件专利问题;
与其他许可证的兼容性;
源代码分割和组成的定义;
解决 () 问题。
2006年,自由软件基金会针对GPL的可能的修改开始了12个月的公共咨询。
GPLv3草稿于开始可用。版本2与3的非官方比较对照参见:,。
日正式启用。
,正式发布了GPL第3版。
以下是对GPL条款的一个通俗易懂的总结。而GPL原文文本才是真正法律上精确的。该文本的链接可从本页底部获得。
授予的权利
此GPL的条款和条件适用于任何收到GPL下的作品的人(即“许可证接受人”)。任何接受这
些条款和条件的许可证接受人都有修改、复制、再发行作品或作品的演绎版本的授权。许可证接受人可以对此项服务收取费用
,反之亦然。这一点是GPL与其他禁止商业用途的自由软件许可证最大的不同。Stallman认为自由软件不应限制其商业用途,同时GPL清楚地说明了这
但GPL又规定发行者不能限制GPL授予的权利。例如,这禁止对软件在单纯沉默(消极默示)式协议或合同下的发行。GPL下的发行者同时也同意在软件中使用的专利可以在其它GPL软件中使用。
GPL不会授予许可证接受人无限的权利。再发行权的授予需要许可证接受人开放软件的,及所有修改。且复制件、修改版本,都必须以GPL为许可证。
这些要求就是copyleft,它的基础就是作品在法律上。由于它版权所有,许可证接受人就无权进行修改和再发行(除),除非它有一个copyleft条款。如果某人想行使通常被法律所禁止的权利,只需同意GPL的条款。相反地,如果某人发行软件违反了GPL(比如不开放源代码),他就有可能被原作者。
copyleft利用版权法来达到与其相反的目的: copyleft给人不可剥夺的权利,而不是版权法所规定的诸多限制。这也是GPL被称作“被黑的版权法”的原因。
许多GPL软件发行者都把源代码与可执行程序捆绑起来。另一方式就是以物理介质(比如)为载体提供源代码。在实践中,许多GPL软件都是在上发行的,源代码也有许多可以方式得到。
copyleft只在程序再发行时发生效力。对软件的修改可以不公开或开放源代码,只要不发行。注意copyleft只对软件有效力,而对软件的输出并无效力(除非输出的是软件本身)。不过这在GPL版本3中可能会有改动。
GPL是许可证
GPL设计为一种许可证,而不是合同。在国家,许可证与合同有法律上的明确区别:合同由合同法保障效力,而GPL作为一种许可证由版权法保障效力。不过在许多采用的国家并无此种区别。
GPL原理简单:在版权法下,你不遵守GPL的条款和条件你就没有相应权利。而作品在没有GPL的情况下,版权法作为默认条款发生效力,而不是作品进入。
版权所有人
GPL文本是版权所有的,且著作权人是自由软件基金会。但是,自由软件基金会没有在GPL下发行作品的著作权(除非作者制定自由软件基金会是著作权人)。只有著作权人才有权对许可证的违反进行起诉。
自由软件基金会允许人们使用以GPL为基础的其他许可证,但不允许演绎的许可证未经授权地使用GPL的前言。不过像这样的许可证通常与GPL不兼容。
GNU计划创立的其他许可证包括:和。
一个关于GPL重要的争议是,非GPL软件是否可以到GPL库。GPL对GPL作品的在
GPL下发布规定很明确。但是对于动态链接到GPL库的作品是否是演绎作品就规定得不清楚了。自由和开放源代码社区为此分成两派,自由软件基金会认为这种
作品就是演绎作品,但其他专家并不同意。这个问题根本的并不关乎GPL本身,而是一个版权法如何定义演绎作品。美国联邦上诉法院第九巡回审判庭在
Galoob v. Nintendo案对演绎作品尝试定义,但最终没有明确的结果。
不幸的是,许多开发者觉得这是个技术问题。但实际上这完全是法律问题。不过由于迄今为止没有案例表明有人以动态链接的方式来绕过GPL的条款或者并被起诉,动态链接的限制已经是事实上地()有效,不论它是否是法律上地()有效。
, AB公司起诉Progress NuSphere侵犯版权和商标。NuSphere被指以链接代码的形式侵犯了著作权。最终此案以调解结束。在听证期间,法官“认为没有什么原因”(不管是否是动态链接)会使得GPL失去法律效力。
,SCO Group称他们认为GPL没有法律效力,且准备就在中使用的SCO Unix代码进行诉讼。参见。
,在SiteCom拒绝停止发行Netfilter项目的GPL软件后,地区法庭据对GPL条款的侵犯判定对SiteCom进行临时性禁令(诉前停止侵犯专利权行为的措施)。同年,法庭确认此勒令为对SiteCom最终判决。此判决明显的印证了自由软件基金会的法律顾问伊本·莫格林的预言:
“被告侵犯了原告的著作权:提供了软件netfilter/iptables的广告及下载,但没有遵守GPL的条款。可以说,如果被告有许可证许
可,这些行为是完全合法的……原被告就GPL是否达成协议这是一个独立的问题。如果当事人没有同意,被告将没有复制、发行、公开
‘netfilter/iptables’的权利。”
此判决十分重要,因为它是全球首次法庭确认GPL是有法律效力的。
,Daniel Wallace于美国联邦印第安纳南区地方法院起诉自由软件基金会,因为二者对GPL是否是非法意见不一。后诉讼于结束,因为Wallace没有有效的反托拉斯陈述。法庭注意到“GPL鼓励,而不是反对电脑操作系统的自由竞争和发行,这直接使消费者受益。”Wallace被拒绝改变诉由,并被要求支付诉讼费用。
大多数许可证,比如、、,都是“GPL兼容的”,即它们的代码与GPL代码混用无冲突(但新代码则是GPL下的)。但是有某些开源软件许可证不是GPL兼容的。通常意见是开发者仅只使用GPL兼容的许可证,以免法律问题。
参见以查证兼容性。
Linux为“癌症”,因为GPL的影响。微软批评者指出,微软憎恶GPL的真正原因是因为对微软的“包围、扩展、消灭”策略起了反作用。注意微软已以
GPL为许可证发行了SFU(Microsoft Windows Services for UNIX)中所包含的部分组件,例如。
GPL的批评者常常认为GPL是有“传染性”的“病毒”
,因为GPL条款规定演绎作品也必须是GPL的。由于“演绎作品”通常被解释为包含GPL代码或动态链接到GPL库(如上)的软件,“病毒说”来源于
GPL对于许可证的强制继承的要求。这正是GPL与BSD式许可证的哲学思想上的差异。GPL的支持者确信自由软件世界应具有自我保护能力和可持续发展性
——确保自由软件的演绎作品同样“自由”,但其他人认为自由软件应给予“所有人”最大的自由。
X-Spirit 阅读(213) |
今天在项目里碰到了非常纠结的问题——中文乱码问题。
原因是这样的,我打算通过JSF的一个FRAME控件LOAD一个jsp页面,该jsp页面根据GET参数得到文件的路径和文件名,从而可以将文件用二进制流输出给浏览器,以便下载。
但是由于我本地的文件名是中文的,所以出现了乱码问题。
简单点说,主要有以下几点:
1. 用java创建本地文件的中文文件名问题:
为了保证你的文件名不会乱码,在用java.io.File对象创建文件的时候,构造函数里的filename千万不要随意的转换成其他字符集的。就用默认的就好。也就是说
File f= new File(“中文文件.txt”);
足矣。这样,无论Windows用GBK编码文件名还是LINUX用UTF-8编码文件名,都可以在当前的系统中正常的查看。
2.向JSP传递中文参数的时候,如果你没有设定Tomcat的全局URIEncoding,一定要把中文参数进行URLEncoding
URLEncoder.encode(requestUrl,"UTF-8");
在被请求的页面,执行URLDecoder.decode(request.getParameter(“param”),"UTF-8");从而得到正确的中文。如果不能,可以尝试“new String(request.getParameter(“param”).getBytes("iso8859_1"),”UTF-8”)”
3.如果你在POST传参的时候发现出了问题,
可以在web.xml里面配置一个CharacterEncodingFillter。这个东西网上有很多代码,自己找吧。如果你用的是Spring,可以用它自带的org.springframework.web.filter.CharacterEncodingFilter
4.另一种解决参数乱码的办法就是修改TOMCAT的配置文件。
找到server.xml。把里面HTTP端口和HTTPS端口(如果你放开了)的Connector元素后面加上URIEncoding=”UTF-8”字样。
X-Spirit 阅读(240) |
做的项目中要用到日志功能,记录重要数据增删改,以提供后台动态数据恢复功能,在数据库中建立一个表四个字段:
id:标识(long)、action:增删改类别(String 或 int)、olddata与newdata分别记录增删改前后的数据类型为blob、optime记录操作时间
项目持久层用了Hibernate所以数据库中所有条目都是以JavaBean形式出现,JavaBean扩展了Serializable可以实现对象的序列化,现在问题就是怎样保存JavaBean序列化的结果到数据库,并且可以逆向反序列化为实例。
因为刚接触Java对列的概念不是很清楚,所以在序列化上遇到了问题,首先是如何不通过临时文件取得对象序列化的结果,网上的例子大多是对文件流的操作,用来保存图片
综合网上的多个例子以及从JDK中查询的结果,总结出以下过程:
1、还是对流的操作,不过不是文件流而是字节流,利用ByteArrayOutputStream创建
2、通过new出来ByteArrayOutputStream作为参数创建ObjectOutputStream
3、调用ObjectOutputStream的writeObject将任意JavaBean序列化为字节流
//以上是序列化过程,实际上使用不同的XStream就可以把JavaBean序列化到不同的流中
4、通过调用ByteArrayOutputStream的toByteArray可以获得byte数组
//这是取中间值,相当于文件流操作时利用文件名打开一个文件流,文件名也是一个中间值
5、将得到的byte数组作为参数用ByteArrayInputStream打开一个输入流
6、调用静态方法Hibernate.createBlob(),以输入流为参数获取Blob
7、此后可将该Blob设置为接收Bean的属性保存到数据库中
//以上完成将序列化的结果存储到数据库
8、利用Hibernate的API的到数据库中的Blob很容易,然后调用Blob的getBinaryStream可获取输入流,将此流作为ObjectInputStream,调用readObject可得到序列化前的实例
ByteArrayOutputStream bos=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(bos);
oos.writeObject(new User("cfgxy"));
//保存到数据库,sessionFactory是Hibernate中SessionFactory的一个实例
Session session=sessionFactory.createSession();
Transaction tx =session.openTransaction();
ByteArrayInputStream bis=new ByteArrayInputStream(bos.getByteArray());
session.save(new Logs(null,"INSERT",null,Hibernate.createBlob(bis)));
tx.commit();
session.close();
//从数据库读取,假设传来的参数id为数据库主键的值
Session session=sessionFactory.createSession();
Logs log=(Logs)session.load(Logs.class,id);
ObjectInputStream ois=new ObjectInputStream(log.getNewData().getBinaryStream());
return (User)ois.readObject();
//代码中均未对异常进行捕捉,实际运用中要捕捉异常
X-Spirit 阅读(1373) |
&java深度历险&一书在讲解“类装载”的一章中,举了以下的例子: 引用 Java代码
public interface Assembly{
public void start();;
public class Word implements Assembly{
System.out.println(&Word static initialization!&);;
public void start();{
System.out.prinlnt(&Word starts&);;
public class Office{
public static void main(String args[]); throws Exception{
Office off = new Office();;
System.out.println(&类别准备载入&);;
Class c = Class.forName(args[0],true,off.getClass();.getClassLoader(););;
System.out.println(&类别准备实例化&);;
Object o = c.newInstance();;
Object o2= c.newInstance();;
执行java Office Word,运行结果如下:“Loaded Office”“类别准备载入”“Loaded Accembly”“Loaded Word””“Word static initialization”“类别准备实体化”。但是如果将Office.java中Class.forName(args[0],true,off.getClass().getClassLoader())中的true变为false,再执行java Office Word结果显示为:“Loaded Office”“类别准备载入”“Loaded Accembly”“Loaded Word””“类别准备实体化”“Word static initialization”。 显然两次红字部分顺序相反,及static块执行的顺序不同。此书作者提出了原因,原文:
引用 “过去很多java书上提到静态初始化(static initializion block)时,都会说静态初始化区块只是在类第一次载入的时候才会被调用仅仅一次。可是上面输出却发现即使类被载入了,其静态初始化区块也没有被调用,而是在第一次调用newInstance方法时,静态初始化块才被真正调用,应该改成-静态初始化块只是在类被第一次实体化的时候才会被仅仅调用一次。” 其实,该书作者的上述描述有误。通过一个试验,就可以看出谬误所在。 Java代码
public class TestA{
System.out.println(&Static block executed!&);;
public class Test{
public static void main(String args[]);{
Test test = new Test();;
Class.forName(&TestA&,true,test.getClass();.getClassLoader(););;
运行一下,相信大家一定可以看到,“Static block executed!”的输出。这与
引用 而是在第一次调用newInstance方法时,静态初始化块才被真正调用 的说法矛盾。其实我想事实是这样的:一个类的运行,JVM做会以下几件事情 1、类装载 2、链接 3、初始化 4、实例化;而初始化阶段做的事情是初始化静态变量和执行静态方法等的工作。所以,当Class.forName(args[0],true,off.getClass().getClassLoader());中的true变为false的时候,就是告诉JVM不需再load class之后进行initial的工作。这样,将initial的工作推迟到了newInstance的时候进行。所以,static块的绝对不是什么“只是在类被第一次实体化的时候才会被仅仅调用一次”,而应该是在类被初始化的时候,仅仅调用一次。
X-Spirit 阅读(126) |
一、性能优化的一般概念
人们普遍认为Java程序总是比C程序慢,对于这种意见,大多数人或许已经听得太多了。实际上,情况远比那些陈旧的主张要复杂。许多 Java程序确实很慢,但速度慢不是所有Java程序的固有特征。许多Java程序可以达到C或C++中类似程序的效率,但只有当设计者和程序员在整个开发过程中密切注意性能问题时,这才有可能。
本文的主要目的是讨论如何优化Java IO操作的性能。许多应用把大量的运行时间花在网络或文件IO操作上,设计拙劣的IO代码可能要比经过精心调整的IO代码慢上几倍。
说到Java程序的性能优化,有些概念总是一次又一次地被提起。本文的示例围绕IO应用的优化展开,但基本原则同样适用于其他性能情况。
对于性能优化来说,最重要的原则也许就是:尽早测试,经常测试。不知道性能问题的根源就无法有效地调整性能,许多程序员因为毫无根据地猜测性能问题的所在而徒劳无功。在一个只占程序总运行时间百分之一的模块上花费数天时间,应用性能的改进程度不可能超过百分之一。所以,应当避免猜测,而是采用性能测试工具,比如一些代码分析工具或带有时间信息的日志,找出应用中耗时最多的地方,然后集中精力优化这些程序的热点。性能调整完成后,应当再次进行测试。测试不仅有助于程序员把精力集中在那些最重要的代码上,而且还能够显示出性能调整是否真地取得了成功。
在调整程序性能的过程中,需要测试的数据可能有很多,例如运行总时间、内存占用平均值、内存占用峰值、程序的吞吐能力、请求延迟时间以及对象创建情况等。到底应该关注哪些因素,这与具体的情况和对性能的要求有关。大部分上述数据都可以通过一些优秀的商品化分析工具测试得到,然而,并非一定要有昂贵的代码分析工具才能收集得到有用的性能数据。
本文收集的性能数据只针对运行时间,测试所用的工具类似于下面的Timer类(可以方便地对它进行扩展,使它支持pause()和 restart()之类的操作)。带有时间信息的日志输出语句会影响测试结果,因为这些语句也要创建对象和执行IO操作,Timer允许我们在不用这类语句的情况下收集时间信息。
public class Timer { // 一个简单的“秒表”类,精度为毫秒。 private long startTime, endT public void start() { startTime = System.currentTimeMillis(); } public void stop() { endTime = System.currentTimeMillis(); } public long getTime() { return endTime - startT } }
引起Java性能问题的常见原因之一是过多地创建临时对象。虽然新的Java虚拟机在创建许多小型对象时有效地降低了性能影响,但对象创建属于昂贵操作这一事实仍旧没有改变。由于字符串对象不可变的特点,String类常常是性能问题最大的罪魁祸首,因为每次修改一个String对象,就要创建一个或者多个新的对象。由此可以看出,提高性能的第二个原则是:避免过多的对象创建操作。
二、IO性能优化
许多应用要进行大规模的数据处理,而IO操作正属于那种细微的改动会导致巨大性能差异的地方。本文的例子来自对一个文字处理应用的性能优化,这个文字处理应用要对大量的文本进行分析和处理。在文字处理应用中,读取和处理输入文本的时间很关键,优化该应用所采用的措施为上面指出的性能优化原则提供了很好的例子。
影响Java IO性能最主要的原因之一在于大量地使用单字符IO操作,即用InputStream.read()和Reader.read()方法每次读取一个字符。 Java的单字符IO操作继承自C语言。在C语言中,单字符IO操作是一种常见的操作,比如重复地调用getc()读取一个文件。C语言单字符IO操作的效率很高,因为getc()和putc()函数以宏的形式实现,且支持带缓冲的文件访问,因此这两个函数只需要几个时钟周期就可以执行完毕。在Java 中,情况完全不同:对于每一个字符,不仅要有一次或者多次方法调用,而且更重要的是,如果不使用任何类型的缓冲,要获得一个字符就要有一次系统调用。虽然一个依赖read()的Java程序可能在表现、功能上和C程序一样,但两者在性能上不能相提并论。幸而,Java提供了几种简单的办法帮助我们获得更好的IO性能。
缓冲可以用以下两种方式之一实现:使用标准的BufferedReader和BufferedInputStream类,或者使用块读取方法一次读取一大块数据。前者快速简单,能够有效地改进性能,且只需少量地增加代码,出错的机会也较少。后者也即自己编写代码,复杂性略有提高——当然也说不上困难,但它能够获得更好的效果。
为测试不同IO操作方式的效率,本文用到了六个小程序,这六个小程序读取几百个文件并分析每一个字符。表一显示了这六个程序的运行时间,测试用到了五个常见的Linux Java虚拟机:Sun 1.1.7、1.2.2和1.3 Java虚拟机,IBM 1.1.8和1.3 Java虚拟机。
这六个程序是:
RawBytes:用FileInputStream.read()每次读取一个字节。
RawChars:用FileReader.read()每次读取一个字符。
BufferedIS:用BufferedInputStream封装FileInputStream,用read()每次读取一个字节的数据。
BufferedR:用BufferedReader封装FileReader,用read()每次读取一个字符。
SelfBufferedIS:用FileInputStream.read(byte[])每次读取1 K数据,从缓冲区访问数据。
SelfBufferedR:用FileReader.read(char[])每次读取1 K数据,从缓冲区访问数据。
BufferedIS
SelfBufferedIS
SelfBufferedR
表一是调整Java VM和程序启动配置之后,处理几百个文件的总计时间。从表一我们可以得到几个显而易见的结论:
InputStream比Reader高效。一个char用两个字节保存字符,而byte只需要一个,因此用byte保存字符消耗的内存和需要执行的机器指令更少。更重要的是,用byte避免了进行Unicode转换。因此,如果可能的话,应尽量使用byte替代char。例如,如果应用必须支持国际化,则必须使用char;如果从一个ASCII数据源读取(比如HTTP或MIME头),或者能够确定输入文字总是英文,则程序可以使用byte。
无缓冲的字符IO实在很慢。字符IO本来就效率不高,如果没有缓冲,情形就更糟了。因此,在编程实践中,至少应该为流加上缓冲,它可以让IO性能提高10倍以上。
带有缓冲的块操作IO要比缓冲的流字符IO快。对于字符IO,虽然缓冲流避免了每次读取字符时的系统调用开销,但仍需要一次或多次方法调用。带缓冲的块IO比缓冲流IO快2到4倍,比无缓冲的IO快4到40倍。
从表一不易看出的一点是,字符IO可能抵消速度较快的Java VM带来的优势。在大多数性能测试中,IBM 1.1.8 Linux Java VM大约有Sun 1.1.7 Linux Java VM两倍那么快,然而在RawBytes和RawChars的测试中,结果显示出两者差不多慢,它们花在系统调用上的额外时间开销掩盖了较快Java VM带来的速度优势。
块IO还有另一个不那么明显的优点。缓冲的字符IO有时对组件之间的协调有更多的要求,带来更多的出错机会。很多时候,应用中的IO操作由一个组件完成,应用把一个Reader或InputStream传递给组件,然后,IO组件处理流的内容。一些IO组件可能错误地假设它所操作的流是一个带缓冲的流,但又不在文档中说明这方面的需求,或者虽然IO组件在文档中说明了这方面的要求,但应用的开发者却未能留意到这一点。在这些情况下,IO 操作将不按意料之中地那样带有缓冲,从而带来严重的性能问题。如果改用块IO,这类情形就不可能出现(因此,设计软件组件时,最好能够做到组件不可能被误用,而不要依赖于文档来保证组件的正确使用)。
从上述简单的测试可以看出,用最直接的方法完成一个简单任务,比如读取文本,可能比细心选择的方法慢40到60倍。在这些测试中,程序在提取和分析每一个字符时进行了一些计算。如果程序只是把数据从一个流复制到另一个流,则非缓冲的字符IO和块IO之间的性能差异将更加明显,块IO的性能将达到非缓冲字符IO的300到500倍。
三、再次测试
性能调整必须反复地进行,因为在主要性能问题解决之前,次要性能问题往往不能显露出来。在文字处理应用的例子中,最初的分析显示出程序把绝大部分的时间花费在读取字符上,加上缓冲功能后性能有了戏剧性的提高。只有在程序解决了主要的性能瓶颈(字符IO)之后,剩余的性能热点才显现出来。对程序的第二次分析显示出,程序在创建String对象上花费了大量的时间,而且看起来它为输入文本中的每一个单词创建了一个以上的String对象。
本文例子中的文本分析应用采用了模块化的设计,用户可以结合多个文本处理操作达到预期的目标。例如,用户可以结合运用单词标识器部件(读取输入字符并把它们组织成单词)和小写字母转换器部件(把单词转换成小写字母),以及一个还原器部件(把单词转换成它们的基本形式,例如,把 jumper和jumped转换成jump)。
虽然模块化构造具有很明显的优点,但这种处理方式会对性能产生负面影响。由于部件之间的接口是固定的(每一个部件都以一个String 作为输入,并输出另一个String),部件之间也许存在一些重复的操作。如果有几个部件经常组合在一起使用,对这些情形进行优化是值得的。
在这个文字处理系统中,从实际使用情况可以看出,用户几乎总是在使用单词标识器部件之后,紧接着使用小写字母转换器部件。单词标识器分析每一个字符,寻找单词边界,同时填充一个单词缓冲区。标识出一个完整的单词之后,单词标识器部件将为它创建一个String对象。调用链中的下一个部件是小写字母转换器部件,这个部件将在前面得到的String上调用String.toLowerCase(),从而创建了另一个String对象。对于输入文本中的每一个单词,顺序使用这两个部件将生成两个String对象。由于单词标识器部件和小写字母转换器部件频繁地一起使用,因此可以添加一个经过优化的小写字母单词标识器,这个标识器具有原来两个部件的功能,但只为每一个单词创建一个String对象,从而有利于提高性能。表二显示了测试结果:
单词标识 + 小写字母转换
结合单词标识和小写字母转换
临时字符串创建时间 (B-C)
从表二我们可以得到几个有用的发现:
对于Java VM 1.1,简单的优化引人注目地提高了性能:大约在百分之二十五到百分之四十五之间。最后一行显示出,创建临时String对象占用了程序A和程序B之间百分之六十到九十的性能增加值。另外,正如其他几个测试项目显示出的,IBM Java VM 1.1运行速度要比Sun Java VM 1.1快。
对于1.2和1.3的Java VM,两个版本之间的性能差异不再那么大,大约只有百分之十到百分之二十五之间,相当于创建临时String对象所耗时间的百分比。这个结果表明,在创建对象实例方面,版本较高的Java VM确实提高了效率,但过多的对象创建操作对性能的影响仍旧值得注意。
对于这类创建大量小型对象的操作,1.3版本的Java VM要比1.1和1.2版本的Java VM快得多。
性能优化是一种需要反复进行的工作。在开发工作的早期阶段开始收集性能数据是值得的,因为这样可以尽早地找出和调整性能热点。通过一些比较简单的改进,比如为IO操作增加缓冲,或在适当的时候用byte替代char,常常可以戏剧性地提高应用的性能。另外,不同的VM之间也有着很大的性能差异,简单地换上一个速度较快的Java VM,可能就让程序的性能向预期的目标跨出了一大步。
X-Spirit 阅读(395) |
Java类如下 public static void downloadFile(String path,String fileName) {try {// 获得JSF上下文环境
FacesContext context = FacesContext.getCurrentInstance();// 获得ServletContext对象
ServletContext servletContext = (ServletContext) context
.getExternalContext().getContext();// 取得文件的绝对路径
String realName = servletContext.getRealPath(path) + &/&
HttpServletResponse httpServletResponse =
(HttpServletResponse) FacesContext
.getCurrentInstance().getExternalContext().getResponse();
downloadFile(httpServletResponse,realName,fileName);
} catch (IOException e) {
e.printStackTrace();
FacesContext.getCurrentInstance().responseComplete();
}public static void downloadFile(HttpServletResponse response,String
realName,String fileName)
throws IOException
response.setHeader(&Content-disposition&,
& filename=& + fileName);
response.setContentType(&application/x-download&);
//File exportFile = new File(realName);
//response.setContentLength((int) exportFile.length());
ServletOutputStream servletOutputStream = response.getOutputStream();byte[] b = new byte[1024];int i = 0;
FileInputStream fis = new java.io.FileInputStream(realName);while ((i = fis.read(b)) & 0) {
servletOutputStream.write(b, 0, i);
} 使用方法 1、在backing bean的方法中调用函数1即可。如Abean中download方法调用了该方法,前台可以这样调用: &h:commandButton value=&download& action=&#{aBean.download}&&&/h:commandButton& 或者 &h:commandLink value=&download& action=&#{fileUploadForm.download}&&&/h:commandLink& 2、jsp页面可以这样调用: &%@ page contentType=&text/ charset=gb2312&%&&%@page import=&java.io.*&%&&%
String filename = &&;if (request.getParameter(&filename&) != null) {
filename =
request.getParameter(&filename&);
framework.util.FileUtils.downloadFile(response,getServletContext().getRealPath(filename),filename);
} catch(final IOException e) {
System.out.println ( &出现IOException.& + e );
} catch(final IllegalStateException e) {
System.out.println ( &出现IllegalStateException.& + e );
%& 于是jsf页面我们可以借助outputlink来调用该页面 &h:outputLink id=&downloadfile&
value=&#{page/FileDownload.jsp?filename=}&&&t:outputText value=&下载文件& /&&/h:outputLink&
X-Spirit 阅读(152) |
最近在单位的电脑上调试程序。由于使用了JPA和OperaMasks这两个在容器启动的时候需要扫描实体Bean和LiteBean的框架,所以,在Tomcat启动初期,系统经常由于大量的对象被创建而不能回收导致PermGen Space Over Flow。在网上经过一番搜索,终于找到了如下的启动参数,经测试多次热部署不会导致VM崩溃。 -Xms128m -Xmx512m -Xmn96m -XX:PermSize=256M -XX:MaxPermSize=256M -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=7 -XX:GCTimeRatio=19 -Xnoclassgc -XX:+DisableExplicitGC -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+CMSPermGenSweepingEnabled -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0 -XX:+CMSClassUnloadingEnabled -XX:-CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=70 -XX:SoftRefLRUPolicyMSPerMB=0
X-Spirit 阅读(145) |
共9页:&&&&3&&&&&&&&
日一二三四五六2526272829301234567891011121314151617181920212223242526272829303112345
随笔分类(28)
随笔档案(90)
文章分类(1)
文章档案(1)
爱折腾的道儒
Doug Lea's Home Page
老王的博客
靠谱IT帅哥
淘宝核心团队
福林的博客
那谁的BLOG
学习新知、发现新朋友
InfoQ中文站
InfoQ英文站
A website for Java Geeks
并发编程网
百度技术沙龙
阅读排行榜
评论排行榜

我要回帖

更多关于 电脑开机自启动设置 的文章

 

随机推荐