仓蓝

日记本

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  23 Posts :: 0 Stories :: 1 Comments :: 0 Trackbacks

#

这个世界每天都在发生着这样或者那样千奇百怪的事情每个人的人生都有着太多的未知数,谁也不知道自己的明天会怎样大多数的情况下都是走一步算一步,所以我们都是应该做的就是活在当下。做政局自己能够把握机遇的事情就可以了,有着太多的奢望到最后或许你什么也没捞到,所有的一切都是空想这样的结果才会让事实说话,虽然说有些事情我们可以掌握但是毕竟是那么的微小,在大自然面前我常常觉得我个人的力量对比是如此的有限,努力提高自己的个人能力,把配合默契本分做好就已经是非常的不错了。相信传动轴命运的转化总会有实现的那么天。常常写一些心得日记本能够放松一下心情舒畅也算是很好的调节器吧,经常保持一个平常心的状态你会活得更加现实意义一点,在稳定增长以后再慢慢的为理想目标管理方向努力奋斗加油。
posted @ 2013-09-25 11:21 cangshi 阅读(333) | 评论 (0)编辑 收藏

中秋还没有放假之前老大就已经出差了,但是他已经给我布置了任务书我想希望在计划好的时间内执行任务吧,有可能之前时间太紧也没有来得及看清楚所以导致细节没有讲清楚,现在倒好,没有能够按照国际惯例时间完成任务算了吧,先按照统筹安排的方法做其他的工作,等待他回来再做那些工作也是可以的,没有什么东西是死而不僵的,必须要灵活机动才能保证时刻都在运转之中吧中。所以一不定期要加强自知的修养多给自己充电,由于拒绝链接这一步之前没有弄过,害得我损失了很多的周期性我想我可能犯下错误观点了,于是赶紧在昨天把还没有生效的链接全部还原了。现在剩下的就是等待老白的更新了,老白这几天倒是没有发生什么异样的举动我想保持原状我就没有什么更多的担心了,老大一直在等待着我的结果呢只要效果,过程没有人管你,所以我的压力还是蛮大的,这一关能不能过就要看近期内的变化了,我是会坚持每天都会观察员的,以后还应该是做个排名更新的记录吧这样对把握时间管理会心里有底一点。加油
posted @ 2013-09-23 11:29 cangshi 阅读(129) | 评论 (0)编辑 收藏

上帝对每个人最公平的是只有时间,他每天给任何一个人的时间都只有二十四小时。把日常工作中的事情按捺不住完了以后我几乎没有多少时间了,所以我也慢慢腾腾失去了更新换代的时间了。间隔了这么久,我实在是挤不出成果而我目前的状况还只是试用期。我所有的努力奋斗还没有达到一个明显的效果,我在跟时间赛跑相对来说我有资源的情况下也才这样,如果说没有资源那么我是否生活不下去了呢,算了吧我最大的愿望就是在最后的一个月里努力把排名推广应用,给老板一个满意的答案吧说太多的废话过日子都是无用的我只是想多做事少说话。这样专心一点心里面的印象会更加深刻一点。好吧今天的作业成绩就至此为止,有机会再慢慢研究工作吧加油。
posted @ 2013-09-17 11:20 cangshi 阅读(133) | 评论 (0)编辑 收藏

我的人生过了二十多个春秋,我觉得我的人生有太多的无奈,很多时候只能一个人默默的去承受,
不敢告诉别人,其实也没必要告诉别人,也无济于事。家里很困难。来自农村,读书高中的时候就已经很紧了。生活老是不及其余表,青黄不接,家里没有经济来源,所有的一切就是几亩地,一年到头也没买到几憏钱。几兄弟都没有读完初中,只有我读大学,但是我为什么就是个好面子的人呢,所有的这些苦涩不想让人知道,穷人的命,没有一楔丁点的人际关系,真是穷得无法形容了。我只想对的时间做对的事过滤器台。
过去的事就让他地[去吧]。下层阶级的局姢性随时晓雾出来。
好了,希望老白对我友好我就感到安慰了,我会把磁力泵的电磁阀修好的,以后的生活就有一点点保障吧
也算是有了个依靠,让老爸老妈放心就行了。






posted @ 2012-11-05 11:03 cangshi 阅读(278) | 评论 (0)编辑 收藏


      当你在配置Struts 2这个应用程序时,安全功能是一个最关键的问题,本文章详细介绍一下这方面的内容,希望对大家有所帮助吧。呵呵,当然,如果有不当之处,也请朋友们指正啊!配置Struts 2应用程序是基于servlet技术的,所以Struts 2的安全策略也可以使用配置文件进行灵活的配置。

配置安全策略时,有两个概念需要清楚的区分 ,用户和角色,简单的说用户为使用计算机的人,可以是个人或组织。角色是一个抽象的概念,泛指职务或者权限。例如,张三,李四,王五三个人,有职员、主管和经理三个职务(权限),张三是用户,张三可以是主管职务,代表张三这个用户含有主管的权利。

不同的servlet容器所提供的用户和角色管理机制是不相同的。我使用的是Tomcat服务器,它提供的用户和角色管理机制文件是在其安装目录下的conf目录中的tomcat-users.xml文件,可以在这个文件里完成对用户和角色的编辑。例如:

  1. <tomcat-users> 
  2.     <role rolename="tomcat"/> 
  3.     <role rolename="role1"/> 
  4.     <user username="tomcat" password="tomcat" roles="tomcat"/> 
  5.     <user username="both" password="tomcat" roles="tomcat,role1"/> 
  6.     <user username="role1" password="tomcat" roles="role1"/> 
  7. </tomcat-users> 

这个文件定义了2个角色(tomcat和role1)和3名用户(tomcat、both和role1)。你可以在tomcat-users.xml文件里定义任意多个用户和角色。

使用Struts 2保护应用程序的资源

Struts 2应用程序的安全策略是通过部署web.xml文件中的security-constraint元素实现的,该元素的语法定义:

  1. <!ELEMENT security-constraint (display-name?, web-resource-collection+, auth-constraint?, user-data-constraint?)>  
  2. <!ELEMENT display-name (#PCDATA)>  
  3. <!ELEMENT web-resource-collection (web-resource-name, description?, url-pattern*, http-method*)>  
  4. <!ELEMENT auth-constraint (description?, role-name*)>  
  5. <!ELEMENT user-data-constraint (description?, transport-guarantee)> 

该语法说明了,security-constraint元素可以有一个可选的display-name子元素,至少一个web-resource-collection子元素,一个可选的auth-constraint子元素和一个可选的user-data-constraint子元素。

web-resource-collection子元素是用来列出打算保护的Web资源,具体的做法是为这些资源设置URL限制,它是通过设置web-resource-collection元素包含的子元素实现的:

◆  web-resource-name:是与受保护资源相关联的名称。该子元素为必须元素。

◆  description:对给定资源的描述。这个子元素为可选元素。

◆  url-pattern:用来设置URL表达式,与这个URL表达式相匹配的URL地址指向的资源将受到保护。该子元素为至少有一个,为必须元素。

◆  http-method:用来表明哪些HTTP方法将受到限制,例如设置为GET那么所有的GET请求就将受到限制。该元素为可选元素。

auth-constraint元素用于指定可以访问该资源用户角色集合。如果没有指定auth-constraint元素,就将安全约束应用于所有角色。它包含下面几个子元素:

◆  description:描述。该元素是可选元素。

◆  role-name:可以访问保护资源的用户角色。该元素可以有多个。

◆  user-data-constraint元素用来设置怎样保护在客户端和Web容器之间传递的数据。

◆  description: 描述。可选元素。

◆  transport-guarantee :该元素有以下几个值

1. NONE,这意味着应用不需要传输保证。

2. INTEGRAL,意味着服务器和客户端之间的数据必须以某种方式发送,而且在传送中数据不能被篡改。

3. CONFIDENTIAL,这意味着传输的数据必须加密。

配置完毕security-constraint元素的基本信息,大致为下面的格式:

  1. <security-constraint> 
  2.     <web-resource-collection> 
  3.         <web-resource-name>Admin Arew</web-resource-name> 
  4.         <url-pattern>*.action</url-pattern> 
  5.     </web-resource-collection> 
  6.     <auth-constraint> 
  7.         <role-name>myeclipseWeb</role-name> 
  8.     </auth-constraint> 
  9. </security-constraint> 

这个security-constraint元素的效果为:只要与表达式"*.action"匹配的请求不是来自拥有"myeclipseWeb"权限的用户,Web容器就会阻断它。在这里还可以使用http-method元素,阻断特定方法的请求,因为没有使用会阻断所有方法提交的请求。

设置完安全策略后,还需要设置让用户有机会提供证明,证明自己有权限访问这个受限资源的登陆方法。允许使用的登陆方法使用login-config元素设置,下面为login-config元素的语法定义:

  1. <!ELEMENT login-config (auth-method?, realm-name?, form-login-config?)>  
  2. <!ELEMENT auth-method (#PCDATA)>  
  3. <!ELEMENT realm-name (#PCDATA)>  
  4. <!ELEMENT form-login-config (form-login-page, form-error-page)> 

login-config子元素的描述如下:
◆  auth-method指定用来验证用户身份的方法。它的值为下面的一个:BASIC、DIGEST、FORM或 CLIENT-CERT
◆  realm-name指定HTTP Basic验证中在标准登陆框中显示的一条提示。
◆  form-login-config元素是在<auth-method>元素值为"FORM"时使用的。它是指定基于表单的登录中应该使用的登录页面和出错页面。如果没有使用基于表单的验证,则忽略这些元素。这个元素的定义如下,其中form-login-page用于指定显示登录页面的资源路径, form-error-page则用于指定用户登录失败时显示出错页面的资源路径。

  1. <!ELEMENT form-login-config (form-login-page, form-error-page)>  
  2. <!ELEMENT form-login-page (#PCDATA)>  
  3. <!ELEMENT form-error-page (#PCDATA)> 

设置完登陆方法后,还应该使用security-role元素,注册允许用来访问受保护资源所有角色。在该元素内部使用一个role-name子元素来注册一个角色。例如:

  1. <security-role> 
  2.     <role-name>myeclipseWeb</role-name> 
  3. </security-role> 

注册了一个"myeclipseWeb"的角色。

演示示例:使用BASIC登陆方法验证用户身份

1.我使用的Servlet容器是Tomcat,找到它的目录下conf目录中的tomcat-users.xml文件打开内容如下:

  1. <?xml version='1.0' encoding='utf-8'?> 
  2. <tomcat-users> 
  3.     <role rolename="myeclipseWeb"/> 
  4.     <role rolename="myeclipseWebservices"/> 
  5.     <user username="webservices" password="webservices-pwd" roles="myeclipseWebservices"/> 
  6.     <user username="admin" password="admin-pwd" roles="myeclipseWeb,myeclipseWebservices"/> 
  7.     <user username="web" password="web-pwd" roles="myeclipseWeb"/> 
  8. </tomcat-users> 

我使用的IDE是myEclipse9.0,它配置好Tomcat下的tomcat-users.xml文件内容如上,我直接使用它了,你也可以添加自己的角色和用户。该文件定义了2个角色和3个用户,每一个用户都由自己的角色(或者说权限,可以有多重权限)。

2.创建Web项目,找到web.xml,配置它,使它支持Struts 2并且启动Struts 2的安全策略

  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <web-app id="WebApp_9" version="2.4"  
  3.          xmlns="http://java.sun.com/xml/ns/j2ee"  
  4.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  5.          xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> 
  6.     <display-name>Struts Blank</display-name> 
  7.     <filter> 
  8.         <filter-name>struts2</filter-name> 
  9.         <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> 
  10.     </filter> 
  11.     <filter-mapping> 
  12.         <filter-name>struts2</filter-name> 
  13.         <url-pattern>/*</url-pattern> 
  14.     </filter-mapping> 
  15.     <welcome-file-list> 
  16.         <welcome-file>index.html</welcome-file> 
  17.     </welcome-file-list> 
  18.     <!--  配置应用程序需要保护的资源与什么角色才可以访问它   --> 
  19.     <security-constraint> 
  20.         <web-resource-collection> 
  21.             <web-resource-name>Admin Arew</web-resource-name> 
  22.             <url-pattern>*.action</url-pattern> 
  23.         </web-resource-collection> 
  24.         <auth-constraint> 
  25.             <role-name>myeclipseWeb</role-name> 
  26.         </auth-constraint> 
  27.     </security-constraint> 
  28.     <!-- 注册可以访问保护资源的角色  --> 
  29.     <security-role> 
  30.         <role-name>myeclipseWeb</role-name> 
  31.     </security-role> 
  32.     <security-role> 
  33.         <role-name>myeclipseWebservices</role-name> 
  34.     </security-role> 
  35.     <!--  设置登录方法  --> 
  36.     <login-config> 
  37.         <auth-method>BASIC</auth-method> 
  38.         <realm-name>User Basic Authentication</realm-name> 
  39.     </login-config> 
  40. </web-app> 

3. 创建接收一个字段信息的动作类:

  1. public class SecureAction extends ActionSupport { 
  2.     private static final long serialVersionUID = 1961430702313132722L; 
  3.     private String username; 
  4.     public String getUsername() { 
  5.         return username; 
  6.     } 
  7.     public void setUsername(String username) { 
  8.         this.username = username; 
  9.     } 
  10.     @Override 
  11.     public String execute() 
  12.     { 
  13.         return SUCCESS; 
  14.     } 

4. 创建struts.xml配置文件,声明动作

  1. <?xml version="1.0" encoding="UTF-8" ?> 
  2. <!DOCTYPE struts PUBLIC 
  3.     "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" 
  4.     "http://struts.apache.org/dtds/struts-2.0.dtd"> 
  5. <struts> 
  6.     <package name="securePackage" extends="struts-default"> 
  7.         <action name="secure" class="struts2.action.SecureAction"> 
  8.             <result name="success">/index.jsp</result> 
  9.         </action> 
  10.     </package> 
  11. </struts> 

5. 创建输入页面input.jsp和结果页面index.jsp

input.jsp:

  1. <body> 
  2.     <s:form action="secure"> 
  3.         <s:textfield name="username" label="Enter your name"></s:textfield> 
  4.         <s:submit value="submit"></s:submit> 
  5.     </s:form> 
  6. </body> 

index.jsp

  1. <body> 
  2.     <s:property value="username"/>,Welcome 
  3. </body> 

6.测试效果,在浏览器输入:http://localhost:8081/SecureTest/input.jsp,得到如下自力式温度调节阀界面:输入"Tom",点击"submit"按钮,查看效果:


看到了登陆框了吧,此时我们要访问的资源是一个受限资源所以要求权限验证顶装式球阀,还记得我们的用户表吧,查看用户表输入用户信息查看结果:

 

输入"webservices"与"webservices-pwd"的用户信息:

 

提示了一个"403"错误,这是因为虽然用户信息正确,但是"webservices"用户的没有"myeclipseWeb"权限。

这次输入一个不存在的用户信息:

这次获得了一个"401"错误,这是登陆失败的提示结果,这里会因浏览器的不同而需要不同次数的失败登陆才会得到这个结果。

接下来输入一个正确的用户,并且拥有"webservices"权限的用户信息:

点击"确定",获得如下结果:

可以看到,我们成功的访问了受保护的资源。若要传中文字,解决方案我已经在前面"配置Struts2"时介绍过了,需要修改Struts 2默认的编码方式还需要修改页面的编码方式,都改为"GBK"。

 

posted @ 2012-03-22 11:21 cangshi 阅读(329) | 评论 (0)编辑 收藏

Java虚拟机技术参数应用详解
      JAVA虚拟机参数主要分为基本和扩展两类,在命令行中输入JAVA_HOME\bin\java 就可得到基本参数列表,在命令行输入JAVA_HOME\bin\java –X 就可得到扩展参数列表。

  基本参数说明:

  -client,-server

  这两个参数用于设置虚拟机使用何种运行模式,client模式启动比较快,但运行时性能和内存管理效率不如server模式,通常用于客户端应用程序。相反,server模式启动比client慢,但可获得更高的运行性能。

  在 windows上,缺省的虚拟机类型为client模式,如果要使用server模式,就需要在启动虚拟机时加-server参数,以获得更高性能,对服务器端应用,推荐采用server模式,尤其是多个CPU的系统。在Linux,Solaris上缺省采用server模式。

  -hotspot

  含义与client相同,jdk1.4以前使用的参数,jdk1.4开始不再使用,代之以client.

  -classpath,-cp

  虚拟机在运行一个类时,需要将其装入内存,虚拟机搜索类的方式和顺序如下:

  Bootstrap classes,Extension classes,User classes.

  Bootstrap 中的路径是虚拟机自带的jar或zip文件,虚拟机首先搜索这些包文件,用System.getProperty("sun.boot.class.path")可得到虚拟机搜索的包名。

  Extension是位于jre\lib\ext目录下的jar文件,虚拟机在搜索完Bootstrap后就搜索该目录下的jar文件。用System. getProperty("java.ext.dirs“)可得到虚拟机使用Extension搜索路径。

  User classes搜索顺序为当前目录、环境变量 CLASSPATH、-classpath.

  -classpath告知虚拟机搜索目录名、jar文档名、zip文档名,之间用分号;分隔。

  例如当你自己开发了公共类并包装成一个common.jar包,在使用common.jar中的类时,就需要用-classpath common.jar 告诉虚拟机从common.jar中查找该类,否则虚拟机就会抛出java.lang.NoClassDefFoundError异常,表明未找到类定义。

  在运行时可用System.getProperty(“java.class.path”)得到虚拟机查找类的路径。

  使用-classpath后虚拟机将不再使用CLASSPATH中的类搜索路径,如果-classpath和CLASSPATH都没有设置,则虚拟机使用当前路径(。)作为类搜索路径。

  推荐使用-classpath来定义虚拟机要搜索的类路径,而不要使用环境变量 CLASSPATH的搜索路径,以减少多个项目同时使用CLASSPATH时存在的潜在冲突。例如应用1要使用a1.0.jar中的类G,应用2要使用 a2.0.jar中的类G,a2.0.jar是a1.0.jar的升级包,当a1.0.jar,a2.0.jar都在CLASSPATH中,虚拟机搜索到第一个包中的类G时就停止搜索,如果应用1应用2的虚拟机都从CLASSPATH中搜索,就会有一个应用得不到正确版本的类G.

  -D<propertyName>=value

  在虚拟机的系统属性中设置属性名/值对,运行在此虚拟机之上的应用程序可用System.getProperty(“propertyName”)得到value的值。

  如果value中有空格,则需要用双引号将该值括起来,如-Dname=“space string”。

  该参数通常用于设置系统级全局变量值,如配置文件路径,应为该属性在程序中任何地方都可访问。

  -verbose[:class|gc|jni]

  在输出设备上显示虚拟机运行信息。

  verbose和verbose:class含义相同,输出虚拟机装入的类的信息,显示的信息格式如下:

  [Loaded java.io.FilePermission$1 from shared objects file]

  当虚拟机报告类找不到或类冲突时可用此参数来诊断来查看虚拟机从装入类的情况。

  -verbose:gc在虚拟机发生内存回收时在输出设备显示信息,格式如下:

  [Full GC 268K->168K(1984K), 0.0187390 secs]

  该参数用来监视虚拟机内存回收的情况。

  -verbose:jni在虚拟机调用native方法时输出设备显示信息,格式如下:

  [Dynamic-linking native method HelloNative.sum …… JNI]

  该参数用来监视虚拟机调用本地方法的情况,在发生jni错误时可为诊断提供便利。

  -version

  显示可运行的虚拟机版本信息然后退出。一台机器上装有不同版本的JDK时

  -showversion

  显示版本信息以及帮助信息。

  -ea[:<packagename>……|:<classname>]

  -enableassertions[:<packagename>……|:<classname>]

  从JDK1.4开始,java可支持断言机制,用于诊断运行时问题。通常在测试阶段使断言有效,在正式运行时不需要运行断言。断言后的表达式的值是一个逻辑值,为true时断言不运行,为false时断言运行,抛出java.lang.AssertionError错误。

  上述参数就用来设置虚拟机是否启动断言机制,缺省时虚拟机关闭断言机制,用-ea可打开断言机制,不加<packagename>和 classname时运行所有包和类中的断言,如果希望只运行某些包或类中的断言,可将包名或类名加到-ea之后。例如要启动包com.foo.util 中的断言,可用命令 –ea:com.foo.util .

  -da[:<packagename>……|:<classname>]

  -disableassertions[:<packagename>……|:<classname>]

  用来设置虚拟机关闭断言处理,packagename和classname的使用方法和-ea相同。

  -esa | -enablesystemassertions

  设置虚拟机显示系统类的断言。

  -dsa | -disablesystemassertions

  设置虚拟机关闭系统类的断言。

  -agentlib:<libname>[=<options>]

  该参数是JDK5新引入的,用于虚拟机装载本地代理库。

  Libname为本地代理库文件名,虚拟机的搜索路径为环境变量PATH中的路径,options为传给本地库启动时的参数,多个参数之间用逗号分隔。在Windows平台上虚拟机搜索本地库名为libname.dll的文件,在 Unix上虚拟机搜索本地库名为libname.so的文件,搜索路径环境变量在不同系统上有所不同,Linux、SunOS、IRIX上为 LD_LIBRARY_PATH,AIX上为LIBPATH,HP-UX上为SHLIB_PATH.

  例如可使用-agentlib:hprof来获取虚拟机的运行情况,包括CPU、内存、线程等的运行数据,并可输出到指定文件中,可用-agentlib:hprof=help来得到使用帮助列表。在jre\bin目录下可发现hprof.dll文件。

  -agentpath:<pathname>[=<options>]

  设置虚拟机按全路径装载本地库,不再搜索PATH中的路径。其他功能和agentlib相同。

  -javaagent:<jarpath>[=<options>]

  虚拟机启动时装入java语言设备代理。Jarpath文件中的mainfest文件必须有Agent-Class属性。代理类要实现public static void premain(String agentArgs, Instrumentation inst)方法。当虚拟机初始化时,将按代理类的说明顺序调用premain方法。

  参见:java.lang.instrument

  扩展参数说明

  -Xmixed

  设置-client模式虚拟机对使用频率高的方式进行Just-In-Time编译和执行,对其他方法使用解释方式执行。该方式是虚拟机缺省模式。

  -Xint

  设置-client模式下运行的虚拟机以解释方式执行类的字节码,不将字节码编译为本机码。

  -Xbootclasspath:path

  -Xbootclasspath/a:path

  -Xbootclasspath/p:path

  改变虚拟机装载缺省系统运行包rt.jar而从-Xbootclasspath中设定的搜索路径中装载系统运行类。除非你自己能写一个运行时,否则不会用到该参数。

  /a:将在缺省搜索路径后加上path 中的搜索路径。

  /p:在缺省搜索路径前先搜索path中的搜索路径。

  -Xnoclassgc

  关闭虚拟机对class的垃圾回收功能。

  -Xincgc

  启动增量垃圾收集器,缺省是关闭的。增量垃圾收集器能减少偶然发生的长时间的垃圾回收造成的暂停时间。但浓浆泵增量垃圾收集器和应用程序并发执行,因此会占用部分CPU在应用程序上的功能。

  -Xloggc:<file>

  将虚拟机每次垃圾回收的信息写到日志文件中,文件名由file指定,文件格式是平文件,内容和-verbose:gc输出内容相同。

  -Xbatch

  虚拟机的缺省运行方式是在后台编译类代码,然后在前台执行代码,使用-Xbatch参数将关闭虚拟机后台编译,在前台编译完成后再执行。

  -Xms<size>

  设置虚拟机可用内存堆的初始大小,缺省单位为字节,该大小为1024的整数倍并且要大于1MB,可用k(K)或m(M)为单位来设置较大的内存数。初始堆大小为2MB.

  例如:-Xms6400K,-Xms256M

  -Xmx<size>

  设置虚拟机内存堆的最大可用大小,缺省单位为字节。该值必须为1024整数倍,并且要大于2MB.可用k(K)或m(M)为单位来设置较大的内存数。缺省堆最大值为64MB.

  例如:-Xmx81920K,-Xmx80M

  当应用程序申请了大内存运行时虚拟机抛出java.lang.OutOfMemoryError: Java heap space错误,就需要使用-Xmx设置较大的可用内存堆泵。

  -Xss<size>

  设置线程栈的大小,缺省单位为字节。与-Xmx类似,也可用K或M来设置较大的值。通常操作系统分配给线程栈的缺省大小为1MB.

  另外也可在java中创建线程对象时设置栈的大小,构造函数原型为Thread(ThreadGroup group, Runnable target, String name, long stackSize)。

  -Xprof

  输出CPU运行时的诊断信息。

  -Xfuture

  对类文件进行严格格式检查,以保证类代码符合类代码规范。为保持向后兼容,虚拟机缺省不进行严格的格式检查。

  -Xrs

  减少虚拟机中操作系统的信号(singals)的使用。该参数通常用在虚拟机以后台服务方式运行时使用(如Servlet)。

  -Xcheck:jni

  调用JNI函数时进行附加的检查,特别地虚拟机将校验传递给JNI函数参数的合法性,在本地代码中遇到非法数据时,虚拟机将报一个致命错误而终止。使用该阀参数后将造成性能下降。

 

posted @ 2012-03-06 10:50 cangshi 阅读(403) | 评论 (0)编辑 收藏

   JAVA之JDK在64位系统默认开启压缩指针分析(请多多指正!)
      Sun的HotSpot VM从JDK5开始会根据运行环境来自动设定VM的一些参数(ergonomics)。其中大家最熟悉的可能是它会自动选择client与server模式、堆的初始和最大大小等。事实上ergonomics会设置非常多的内部参数,包括自动选择GC算法、并行GC的线程数、GC的工作区分块大小、对象晋升阈值等等。

  Ergonomics相关的逻辑大都在hotspot/src/share/vm/runtime/arguments.cpp中,值得留意的是使用了FLAG_SET_ERGO()的地方。

  于是我们可以留意一下几个版本的HotSpot对UseCompressedOops参数的处理的差异:

  HotSpot 16:

  C++代码

  • #ifdef _LP64     
  •   // Check that UseCompressedOops can be set with 
    the max heap size allocated   
     
  •   // by ergonomics.     
  •   if (MaxHeapSize <= max_heap_for_compressed_oops()) {     
  •     if (FLAG_IS_DEFAULT(UseCompressedOops)) {     
  •       // Turn off until bug is fixed.     
  •       // the following line to return it to default status.     
  •       // FLAG_SET_ERGO(bool, UseCompressedOops, true);     
  •     }     
  •     // ...     
  •   }     
  • #endif // _LP64
  •   HotSpot 17:

      C++代码

  • #ifndef ZERO     
  • #ifdef _LP64     
  •   // Check that UseCompressedOops can be set with 
    the max heap size allocated   
     
  •   // by ergonomics.     
  •   if (MaxHeapSize <= max_heap_for_compressed_oops()) {     
  • #ifndef COMPILER1     
  •     if (FLAG_IS_DEFAULT(UseCompressedOops) && !UseG1GC) {     
  •       // Disable Compressed Oops by default. Uncomment 
    next line to enable it.   
     
  •       // FLAG_SET_ERGO(bool, UseCompressedOops, true);     
  •     }     
  •   }     
  • #endif     
  •   // ...     
  • #endif // _LP64     
  • #endif // !ZERO    
  •   HotSpot 19 / HotSpot 20:

      C++代码

  • #ifndef ZERO     
  • #ifdef _LP64     
  •   // Check that UseCompressedOops can be set with 
    the max heap size allocated   
     
  •   // by ergonomics.     
  •   if (MaxHeapSize <= max_heap_for_compressed_oops()) {     
  • #ifndef COMPILER1     
  •     if (FLAG_IS_DEFAULT(UseCompressedOops) && !UseG1GC) {     
  •       FLAG_SET_ERGO(bool, UseCompressedOops, true);     
  •     }     
  • #endif     
  •   }     
  •   // ...     
  • #endif // _LP64     
  • #endif // !ZERO
  •   (注:HotSpot VM的版本号与JDK的版本号之间的关系,请参考另一篇笔记:Sun/Oracle JDK、OpenJDK、HotSpot VM版本之间的对应关系)

      可以看到,UseCompressedOops参数从HotSpot 19开始终于开始受ergonomics控制,会在下述条件满足的时候默认开启管道磁力泵

      1、是64位系统(#ifdef _LP64)并且不是client VM(#ifndef COMPILER1);

      2、Java堆的最大大小不大于一个阈值(MaxHeapSize <= max_heap_for_compressed_oops());

      3、没有通过。hotspotrc或命令行参数手动设定过UseCompressedOops参数的值;

      4、没有使用Garbage-First (G1) GC.


    第1、3、4点都很直观,于是第2点就是个关键点了:阈值是多大?

      还是看回代码,HotSpot 20:

      C++代码

  • void set_object_alignment() {     
  •   // Object alignment.     
  •   assert(is_power_of_2(ObjectAlignmentInBytes), "ObjectAlignmentInBytes must be power of 2");     
  •   MinObjAlignmentInBytes     = ObjectAlignmentInBytes;     
  •   assert(MinObjAlignmentInBytes >= HeapWordsPerLong * HeapWordSize, 
    "ObjectAlignmentInBytes value is too small");     
  •   MinObjAlignment         = MinObjAlignmentInBytes / HeapWordSize;     
  •   assert(MinObjAlignmentInBytes == MinObjAlignment * HeapWordSize, 
    "ObjectAlignmentInBytes value is incorrect");     
  •   MinObjAlignmentInBytesMask = MinObjAlignmentInBytes - 1;     
  •     
  •   LogMinObjAlignmentInBytes  = exact_log2(ObjectAlignmentInBytes);     
  •   LogMinObjAlignment         = LogMinObjAlignmentInBytes - LogHeapWordSize;     
  •     
  •   // Oop encoding heap max     
  •   OopEncodingHeapMax = (uint64_t(max_juint) + 1) << LogMinObjAlignmentInBytes;     
  • }     
  •     
  • inline uintx max_heap_for_compressed_oops() {     
  •   // Avoid sign flip.     
  •   if (OopEncodingHeapMax < MaxPermSize + os::vm_page_size()) {     
  •     return 0;     
  •   }     
  •   LP64_ONLY(return OopEncodingHeapMax - MaxPermSize - os::vm_page_size());     
  •   NOT_LP64(ShouldNotReachHere(); return 0);     
  • }
  •   (注:其中 (uint64_t(max_juint) + 1) 的值也被称为NarrowOopHeapMax,也就是2的32次方,0x100000000;

      ObjectAlignmentInBytes在64位HotSpot上默认为8;

      HeapWord在globalDefinitions.hpp里定义,大小跟一个char*一样;

      HeapWordSize在同一个文件里定义,等于sizeof(HeapWord),在64位系统上值为8;

      LogHeapWordSize也在同一文件里,在64位系统上定义为3)

      跟踪一下里面几个参数的计算,在64位HotSpot上有,

      C++代码

    1. ObjectAlignmentInBytes = 8     
    2. MinObjAlignmentInBytes = 8     
    3. HeapWordSize = 8     
    4. MinObjAlignment = 1     
    5. MinObjAlignmentInBytesMask = 0x0111     
    6. LogMinObjAlignmentInBytes = 3     
    7. LogHeapWordSize = 3 // _LP64     
    8. LogMinObjAlignment = 0     
    9. OopEncodingHeapMax = 0x800000000 // 32GB    

      于是,前面提到的第2个条件在64位HotSpot VM上默认是:

      C++代码

  • MaxHeapSize + MaxPermSize + os::vm_page_size() <= 32GB
  •   os::vm_page_size()是操作系统的虚拟内存的分页大小,在Linux上等于sysconf(_SC_PAGESIZE)的值;在x86_64上的Linux默认分页大小为4KB.

      MaxHeapSize的值基本上等于-Xmx参数设置的值(会根据分页大小、对齐等因素做调整)。

      MaxPermSize就是perm gen设置的最大大小。

      这下可以确认,在我现在用的环境里,当包括perm gen在内的GC堆大小在32GB - 4KB以下的时候,使用64位的JDK 6 update 23或更高版本就会自动开启UseCompressedOops功能


    posted @ 2012-03-02 11:07 cangshi 阅读(2233) | 评论 (0)编辑 收藏

    深入解析Java核心内容:JVM中的栈和局部变量
            总的来说,深入Java核心其实最主要包含个方面的内容:JVM中的栈和局部变量 Java内存分配原理  Java垃圾回收机制  Java中多态的实现机制

    Java中的栈

    每当启用一个线程时,JVM就为他分配一个Java栈,栈是以帧为单位保存当前线程的运行状态。某个线程正在执行的方法称为当前方法,当前方法使用的栈帧称为当前帧,当前方法所属的类称为当前类,当前类的常量池称为当前常量池。当线程执行一个方法时,它会跟踪当前常量池。

    每当线程调用一个Java方法时,JVM就会在该线程对应的栈中压入一个帧,这个帧自然就成了当前帧。当执行这个方法时,它使用这个帧来存储参数、局部变量、中间运算结果等等。

    Java栈上的所有数据都是私有的。任何线程都不能访问另一个线程的栈数据。所以我们不用考虑多线程情况下栈数据访问同步的情况。

    像方法区和堆一样,Java栈和帧在内存中也不必是连续的,帧可以分布在连续的栈里,也可以分布在堆里

    Java栈的组成元素——栈帧

    栈帧由三部分组成:局部变量区、操作数栈、帧数据区。局部变量区和操作数栈的大小要视对应的方法而定,他们是按字长计算的。但调用一个方法时,它从类型信息中得到此方法局部变量区和操作数栈大小,并据此分配栈内存,然后压入Java栈。

    局部变量区 局部变量区被组织为以一个字长为单位、从0开始计数的数组,类型为short、byte和char的值在存入数组前要被转换成int值,而long和 double在数组中占据连续的两项,在访问局部变量中的long或double时,只需取出连续两项的第一项的索引值即可,如某个long值在局部变量区中占据的索引时3、4项,取值时,指令只需取索引为3的long值即可。

    下面就看个例子,好让大家对局部变量区有更深刻的认识。这个图来自《深入JVM》:

    1. public static int runClassMethod(int i,long l,float f,double d,Object o,byte b) {     
    2.         return 0;     
    3.     }     
    4.          
    5.     public int runInstanceMethod(char c,double d,short s,boolean b) {     
    6.         return 0;     
    7.     }    

    上面代码片的方法参数和局部变量在局部变量区中的存储结构如下图:

    局部变量区的存储结构

    上面这个图没什么好说的,大家看看就会懂。但是,在这个图里,有一点需要注意:

    runInstanceMethod的局部变量区第一项是个reference(引用),它指定的就是对象本身的引用,也就是我们常用的this,但是在runClassMethod方法中,没这个引用,那是因为runClassMethod是个静态方法。


    操作数栈和局部变量区一样,操作数栈也被组织成一个以字长为单位的数组。但和前者不同的是,它不是通过索引来访问的,而是通过入栈和出栈来访问的。可把操作数栈理解为存储计算时,临时数据的存储区域。下面我们通过一段简短的程序片段外加一幅图片来了解下操作数栈的作用。

    int a = 100;

    int b = 98;

    int c = a+b;

    操作数栈的结构

    从图中可以得出:操作数栈其实就是个临时数据存储区域,它是通过入栈和出栈来进行操作的。

    帧数据区除了局部变量区和操作数栈外,Java栈帧还需要一些数据来支持常量池解析、正常方法返回以及异常派发机制。这些数据都保存在Java栈帧的帧数据区中。
    当JVM执行到需要常量池数据的指令时,它都会通过帧数据区中指向常量池的指针来访问它。

    除了处理常量池解析外,帧里的数据还要处理Java方法的正常结束和异常终止。如果是通过return正常结束,则当前栈帧从Java栈中弹出,恢复玻璃钢液下泵发起调用的方法的栈。如果方法又返回值,JVM会把返回值压入到发起调用方法的操作数栈。

    为了处理Java方法中的异常情况,帧数据区还必须保存一个对此方法异常引用表的引用。当异常抛出时,JVM给catch块中的代码。如果没发现,方法立即终止,然后JVM用帧区数据的信息恢复发起调用的方法的帧。然后再发起调用方法的上下文重新抛出同样的异常。

    栈的整个结构

    在前面就描述过:栈是由栈帧组成,每当线程调用一个Java方法时,JVM就会在该线程对应的栈中压入一个帧,而帧是由局部变量区、操作数栈和帧数据区组成。那在一个代码块中,栈到底是什么形式呢?下面是我从《深入JVM》中摘抄的一个例子,大家可以看看:

    代码片段:

    栈的整个结构代码示例

     

    执行过程中的三个快照:

     

    上面所给的图,只想说明两件事情,我们也可用此来理解Java中的栈:

    1、只有在调用一个方法时,才为当前栈分配一个帧,然后将该帧压入栈。

    2、帧中存储了对应方法的局部数据,方法执行完,对应的帧则从栈中弹出,并把返回结果存储在调用方法的帧的操作数栈中。


    posted @ 2012-02-29 10:52 cangshi 阅读(547) | 评论 (0)编辑 收藏

        加密利用:DES加密Java源码的原因应用分析
      Java源代码经过编译以后在JVM中执行。由于JVM界面是完全透明的,Java类文件能够很容易通过反编译器重新转换成源代码。因此,所有的算法、类文件等都可以以源代码的形式被公开,使得软件不能受到保护,为了保护产权,一般可以有以下几种方法:

      (1)"模糊"类文件,加大反编译器反编译源代码文件的难度。然而,可以修改反编译器,使之能够处理这些模糊类文件。所以仅仅依赖"模糊类文件"来保证代码的安全是不够的。

      (2)流行的加密工具对源文件进行加密,比如PGP(Pretty Good Privacy)或GPG(GNU Privacy Guard)。这时,最终用户在运行应用之前必须先进行解密。但解密之后,最终用户就有了一份不加密的类文件,这和事先不进行加密没有什么差别。

      (3)加密类文件,在运行中JVM用定制的类装载器(Class Loader)解密类文件。Java运行时装入字节码的机制隐含地意味着可以对字节码进行修改。JVM每次装入类文件时都需要一个称为ClassLoader的对象,这个对象负责把新的类装入正在运行的JVM。JVM给ClassLoader一个包含了待装入类(例如java.lang.Object)名字的字符串,然后由ClassLoader负责找到类文件,装入原始数据,并把它转换成一个Class对象。

      用户下载的是加密过的类文件,在加密类文件装入之时进行解密,因此可以看成是一种即时解密器。由于解密后的字节码文件永远不会保存到文件系统,所以窃密者很难得到解密后的代码。

      由于把原始字节码转换成Class对象的过程完全由系统负责,所以创建定制ClassLoader对象其实并不困难,只需先获得原始数据,接着就可以进行包含解密在内的任何转换。

      Java密码体系和Java密码扩展

      Java密码体系(JCA)和Java密码扩展(JCE)的设计目的是为Java提供与实现无关的加密函数API。它们都用factory方法来创建类的例程,然后把实际的加密函数委托给提供者指定的底层引擎,引擎中为类提供了服务提供者接口在Java中实现数据的加密/解密,是使用其内置的JCE(Java加密扩展)来实现的。Java开发工具集1.1为实现包括数字签名和信息摘要在内的加密功能,推出了一种基于供应商的新型灵活应用编程接口。Java密码体系结构支持供应商的互操作,同时支持硬件和软件实现。

      Java密码学结构设计遵循两个原则:

      (1)算法的独立性和可靠性。

      (2)实现的独立性和相互作用性。

      算法的独立性是通过定义密码服务类来获得。用户只需了解密码算法的概念,而不用去关心如何实现这些概念。实现的独立性和相互作用性通过密码服务提供器来实现。密码服务提供器是实现一个或多个密码服务的一个或多个程序包。软件开发商根据一定接口,将各种算法实现后,打包成一个提供器,用户可以安装不同的提供器。安装和配置提供器,可将包含提供器的ZIP和JAR文件放在CLASSPATH下,再编辑Java安全属性文件来设置定义一个提供器。Java运行环境Sun版本时, 提供一个缺省的提供器Sun。

      下面介绍DES算法及如何利用DES算法加密和解密类文件的步骤。

      DES算法简介

      DES(Data Encryption Standard)是发明最早的最广泛使用的分组对称加密算法。DES算法的入口参数有三个:Key、Data、Mode。其中Key为8个字节共64位,是DES算法的工作密钥;Data也为8个字节64位,是要被加密或被解密的数据;Mode为DES的工作方式,有两种:加密或解密。

      DES算法工作流程如下:若Mode为加密模式,则利用Key 对数据Data进行加密, 生成Data的密码形式(64位)作为DES的输出结果;如Mode为解密模式,则利用Key对密码形式的数据Data进行解密,还原为Data的明码形式(64位)作为DES的输出结果。在上海针型阀通信网络的两端,双方约定一致的Key,在通信的源点用Key对核心数据进行DES加密,然后以密码形式在公共通信网(如电话网)中传输到通信网络的终点,数据到达目的地后,用同样的Key对密码数据进行解密,便再现了明码形式的核心数据。这样,便保证了核心数据在公共通信网中传输的安全性和可靠性。

      也可以通过定期在通信网络的源端和目的端同时改用新的Key,便能更进一步提高数据的保密性。
      利用DES算法加密的步骤

      (1)生成一个安全密钥。在加密或解密任何数据之前需要有一个密钥。密钥是随同被加密的应用程序一起发布的一段数据,密钥代码如下所示。

      【生成一个密钥代码】

    view plaincopy to clipboardprint?
    // 生成一个可信任的随机数源
    SecureRandom sr = new SecureRandom();
    // 为我们选择的DES算法生成一个KeyGenerator对象
    KeyGenerator kg = KeyGenerator.getInstance ("DES" );
    Kg.init (sr);
    // 生成密钥
    Secret Key key = kg.generateKey();
    // 将密钥数据保存为文件供以后使用,其中key Filename为保存的文件名
    Util.writeFile (key Filename, key.getEncoded () );
    // 生成一个可信任的随机数源
    SecureRandom sr = new SecureRandom();
    // 为我们选择的DES算法生成一个KeyGenerator对象
    KeyGenerator kg = KeyGenerator.getInstance ("DES" );
    Kg.init (sr);
    // 生成密钥
    Secret Key key = kg.generateKey();
    // 将密钥数据保存为文件供以后使用,其中key Filename为保存的文件名
    Util.writeFile (key Filename, key.getEncoded () );

      (2)加密数据。得到密钥之后,接下来就可以用它加密数据。如下所示。

      【用密钥加密原始数据】

     

    view plaincopy to clipboardprint?
    // 产生一个可信任的随机数源
    SecureRandom sr = new SecureRandom();
    //从密钥文件key Filename中得到密钥数据
    Byte rawKeyData = Util.readFile (key Filename);
    // 从原始密钥数据创建DESKeySpec对象
    DESKeySpec dks = new DESKeySpec (rawKeyData);
    // 创建一个密钥工厂,然后用它把DESKeySpec转换成Secret Key对象
    SecretKeyFactory key Factory = SecretKeyFactory.getInstance("DES" );
    Secret Key key = keyFactory.generateSecret( dks );
    // Cipher对象实际完成加密操作
    Cipher cipher = Cipher.getInstance( "DES" );
    // 用密钥初始化Cipher对象
    cipher.init( Cipher.ENCRYPT_MODE, key, sr );
    // 通过读类文件获取需要加密的数据
    Byte data = Util.readFile (filename);
    // 执行加密操作
    Byte encryptedClassData = cipher.doFinal(data );
    // 保存加密后的文件,覆盖原有的类文件。
    Util.writeFile( filename, encryptedClassData );
    // 产生一个可信任的随机数源
    SecureRandom sr = new SecureRandom();
    //从密钥文件key Filename中得到密钥数据
    Byte rawKeyData = Util.readFile (key Filename);
    // 从原始密钥数据创建DESKeySpec对象
    DESKeySpec dks = new DESKeySpec (rawKeyData);
    // 创建一个密钥工厂,然后用它把DESKeySpec转换成Secret Key对象
    SecretKeyFactory key Factory = SecretKeyFactory.getInstance("DES" );
    Secret Key key = keyFactory.generateSecret( dks );
    // Cipher对象实际完成加密操作
    Cipher cipher = Cipher.getInstance( "DES" );
    // 用密钥初始化Cipher对象
    cipher.init( Cipher.ENCRYPT_MODE, key, sr );
    // 通过读类文件获取需要加密的数据
    Byte data = Util.readFile (filename);
    // 执行加密操作
    Byte encryptedClassData = cipher.doFinal(data );
    // 保存加密后的文件,覆盖原有的类文件。
    Util.writeFile( filename, encryptedClassData );

     

      (3)解密数据。运行经过加密的程序时,ClassLoader分析并解密类文件。操作步骤如下所示。

      【用密钥解密数据】

    view plaincopy to clipboardprint?
    // 生成一个可信任的随机数源
    SecureRandom sr = new SecureRandom();
    // 从密钥文件中获取原始密钥数据
    Byte rawKeyData = Util.readFile( keyFilename );
    // 创建一个DESKeySpec对象
    DESKeySpec dks = new DESKeySpec (rawKeyData);
    // 创建一个密钥工厂,然后用它把DESKeySpec对象转换成Secret Key对象
    SecretKeyFactory key Factory = SecretKeyFactory.getInstance( "DES" );
    SecretKey key = keyFactory.generateSecret( dks );
    // Cipher对象实际完成解密操作
    Cipher cipher = Cipher.getInstance( "DES" );
    // 用密钥初始化Cipher对象
    Cipher.init( Cipher.DECRYPT_MODE, key, sr );
    // 获得经过加密的数据
    Byte encrypted Data = Util.readFile (Filename);
    //执行解密操作
    Byte decryptedData = cipher.doFinal( encryptedData );
    // 然后将解密后的数据转化成原来的类文件。
    // 生成一个可信任的随机数源
    SecureRandom sr = new SecureRandom();
    // 从密钥文件中获取原始密钥数据
    Byte rawKeyData = Util.readFile( keyFilename );
    // 创建一个DESKeySpec对象
    DESKeySpec dks = new DESKeySpec (rawKeyData);
    // 创建一个密钥工厂,然后用它把DESKeySpec对象转换成Secret Key对象
    SecretKeyFactory key Factory = SecretKeyFactory.getInstance( "DES" );
    SecretKey key = keyFactory.generateSecret( dks );
    // Cipher对象实际完成解密操作
    Cipher cipher = Cipher.getInstance( "DES" );
    // 用密钥初始化Cipher对象
    Cipher.init( Cipher.DECRYPT_MODE, key, sr );
    // 获得经过加密的数据
    Byte encrypted Data = Util.readFile (Filename);
    //执行解密操作
    Byte decryptedData = cipher.doFinal( encryptedData );
    // 然后将解密后的数据转化成原来的类文件。

      将上述代码与自定义的类装载器结合就可以做到边解密边运行,从而起到保护源代码的作用。

      结束语

      加密/解密是数据传输中保证数据安全性和完整性的常用方法,Java语言因其平台无关性,在Internet上的应用非常之广泛。使用DES算法加密Java源码在一定程度上能保护软件的产权。

     

    posted @ 2012-02-09 13:34 cangshi 阅读(494) | 评论 (0)编辑 收藏

    公司做web service的时候,看了一下资料,当时看见一个叫rmi的东西(远程方法调用),最近闲着,所以看了一下 ,感觉挺简单的!所以写了一个例子提供给大家把!

    rmi的服务端,必须要使用接口,同时还有接口的实现类!所以下面的两个文件是接口类和接口的实现类!

    UserDao 接口:

    1. /**  
    2.  * 远程接口     必须继承与Remote对象  
    3.  * @author spring sky  
    4.  * date: 2012年2月7日 10:55:05  
    5.  * Email:vipa1888@163.com  
    6.  * QQ:840950105  
    7.  */ 
    8. public interface UserDao extends Remote{  
    9.     /**  
    10.      * 简单的测试方法  
    11.      * @param name  
    12.      */ 
    13.     public void sayName(String name) throws RemoteException;   
    14.  
    15.  

    UserDaoImpl实现类

    1. /**  
    2.  *   
    3.  *  接口的实现类    必须继承UnicastRemoteObject(单一远程对象)   实现UserDao自己的接口  
    4.  * @author spring sky  
    5.  * date: 2012年2月7日 10:56:05  
    6.  * Email:vipa1888@163.com  
    7.  * QQ:840950105  
    8.  */ 
    9. public class UserDaoImpl extends UnicastRemoteObject implements UserDao {  
    10.  
    11.     public UserDaoImpl() throws RemoteException {  
    12.     }  
    13.     @Override 
    14.     public void sayName(String name) {  
    15.         if(name!=null&&!name.equals(""))  
    16.         {  
    17.             System.out.println("我的名字是:"+name);  
    18.         }else{  
    19.             System.err.println("名字不为空....");  
    20.         }  
    21.     }  
    22.  

    对外的提供一个服务,服务中已经共享了url给外界访问

    1. /**  
    2.  * 使用main方法启动一个服务,用于外界环境访问  
    3.  * @author spring sky  
    4.  * date:2012年2月7日 10:57:37  
    5.  * Email:vipa1888@163.com  
    6.  * QQ:840950105  
    7.  */ 
    8. public class StartService {  
    9.     private static final String IP = "127.0.0.1";  
    10.     private static final int PORT = 9999;  
    11.     private static final String REMOTE_NAME = "userDao";  
    12.     private static final String REMOTE_URL = "rmi://"+IP+":"+PORT+"/"+REMOTE_NAME;  
    13.     public static void main(String[] args) {  
    14.         try {  
    15.             UserDao userDao = new UserDaoImpl();    //实例化对象  
    16.             LocateRegistry.createRegistry(PORT);    //注册端口  
    17.             Naming.bind(REMOTE_URL, userDao);       //绑定远程服务对象  
    18.             System.out.println("远程"+REMOTE_NAME+"启动成功....");  
    19.         } catch (RemoteException e) {  
    20.             System.err.println("远程对象出错");  
    21.             e.printStackTrace();  
    22.         } catch (MalformedURLException e) {  
    23.             System.err.println("URL出错了");  
    24.             e.printStackTrace();  
    25.         } catch (AlreadyBoundException e) {  
    26.             System.err.println("绑定的对象已经存在了");  
    27.             e.printStackTrace();  
    28.         }  
    29.     }  

    上面是服务端的代码,如果启动没有任何问题,就可以做客户端访问了,其实上海旋塞阀客户端的访问更加的简单,只需要远程的接口类和查询rmi中的url就可以了!

    代码如下:

    1. /**  
    2.  * 远程方法调用测试  
    3.  * @author spring sky  
    4.  * date:2012年2月7日 11:12:46  
    5.  * Email:vipa1888@163.com  
    6.  * QQ:840950105  
    7.  * name:石明政  
    8.  */ 
    9. public class TestRemote {  
    10.     public static void main(String[] args) {  
    11.         try {  
    12.             //在rmi服务中查询userdao的对象  
    13.             UserDao userDao = (UserDao) Naming.lookup("rmi://127.0.0.1:9999/userDao");     
    14.             //调用远程服务的方法  
    15.             userDao.sayName("spring sky");  
    16.         } catch (MalformedURLException e) {  
    17.             System.err.println("URL出错");  
    18.             e.printStackTrace();  
    19.         } catch (RemoteException e) {  
    20.             System.err.println("远程对象出错");  
    21.             e.printStackTrace();  
    22.         } catch (NotBoundException e) {  
    23.             System.err.println("没有找到绑定的对象");  
    24.             e.printStackTrace();  
    25.         }  
    26.     }  

    以上就是所有的rmi远程调用代码了!运行结果如下:

    好了,本人也只是简单的了解了rmi,如果以后有项目做rmi就可以深入了! 呵呵  ,在这里我突然感觉,想web service也应该和他一样的原理的把!


    posted @ 2012-02-09 10:53 cangshi 阅读(258) | 评论 (0)编辑 收藏

    仅列出标题
    共3页: 上一页 1 2 3 下一页