qileilove

blog已经转移至github,大家请访问 http://qaseven.github.io/

Java防止SQL注入的几个途径

 JavaSQL注入,最简单的办法是杜绝SQL拼接,SQL注入攻击能得逞是因为在原有SQL语句中加入了新的逻辑,如果使用PreparedStatement来代替Statement来执行SQL语句,其后只是输入参数,SQL注入攻击手段将无效,这是因为PreparedStatement不允许在不同的插入时间改变查询的逻辑结构,大部分的SQL注入已经挡住了,在WEB层我们可以过滤用户的输入来防止SQL注入比如用Filter来过滤全局的表单参数。

  • import java.io.IOException;  
  • import java.util.Iterator;  
  • import javax.servlet.Filter;  
  • import javax.servlet.FilterChain;  
  • import javax.servlet.FilterConfig;  
  • import javax.servlet.ServletException;  
  • import javax.servlet.ServletRequest;  
  • import javax.servlet.ServletResponse;  
  • import javax.servlet.http.HttpServletRequest;  
  • import javax.servlet.http.HttpServletResponse;  
  • /** 
  • * 通过Filter过滤器来防SQL注入攻击 
  • * 
  • */ 
  • public class SQLFilter implements Filter {  
  • private String inj_str = "'|and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare|; |or|-|+|,";  
  • protected FilterConfig filterConfig = null;  
  • /** 
  • * Should a character encoding specified by the client be ignored? 
  • */ 
  • protected boolean ignore = true;  
  • public void init(FilterConfig config) throws ServletException {  
  • this.filterConfig = config;  
  • this.inj_str = filterConfig.getInitParameter("keywords");  
  • }  
  • public void doFilter(ServletRequest request, ServletResponse response,  
  • FilterChain chain) throws IOException, ServletException {  
  • HttpServletRequest req = (HttpServletRequest)request;  
  • HttpServletResponse res = (HttpServletResponse)response;  
  • Iterator values = req.getParameterMap().values().iterator();//获取所有的表单参数 
  • while(values.hasNext()){  
  • String[] value = (String[])values.next();  
  • for(int i = 0;i < value.length;i++){  
  • if(sql_inj(value[i])){  
  • //TODO这里发现sql注入代码的业务逻辑代码 
  • return;  
  • }  
  • }  
  • }  
  • chain.doFilter(request, response);  
  • }  
  • public boolean sql_inj(String str)  
  • {  
  • String[] inj_stra=inj_str.split("\\|");  
  • for (int i=0 ; i < inj_stra.length ; i++ )  
  • {  
  • if (str.indexOf(" "+inj_stra[i]+" ")>=0)  
  • {  
  • return true;  
  • }  
  • }  
  • return false;  
  • }  
  • }
  •   也可以单独在需要防范SQL注入的JavaBean的字段上过滤:

  • /** 
  • * 防止sql注入 
  • * 
  • * @param sql 
  • * @return 
  • */ 
  • public static String TransactSQLInjection(String sql) {  
  • return sql.replaceAll(".*([';]+|(--)+).*"" ");  
  • }
  • posted @ 2012-01-04 10:46 顺其自然EVO 阅读(232) | 评论 (0)编辑 收藏

    Java并发编程:守护线程

    Java中有两类线程:用户线程(UserThread)、守护线程(DaemonThread)。

      所谓守护线程,是指在程序运行的时候在后台提供一种通用服务的线程,比如垃圾回收线程就是一个很称职的守护者,并且这种线程并不属于程序中不可或缺的部分。因此,当所有的非守护线程结束时,程序也就终止了,同时会杀死进程中的所有守护线程。反过来说,只要任何非守护线程还在运行,程序就不会终止。

      用户线程和守护线程两者几乎没有区别,唯一的不同之处就在于虚拟机的离开:如果用户线程已经全部退出运行了,只剩下守护线程存在了,虚拟机也就退出了。因为没有了被守护者,守护线程也就没有工作可做了,也就没有继续运行程序的必要了。

      将线程转换为守护线程可以通过调用Thread对象的setDaemon(true)方法来实现。在使用守护线程时需要注意一下几点:

      (1)thread.setDaemon(true)必须在thread.start()之前设置,否则会跑出一个IllegalThreadStateException异常。你不能把正在运行的常规线程设置为守护线程。

      (2)在Daemon线程中产生的新线程也是Daemon的。

      (3)守护线程应该永远不去访问固有资源,如文件、数据库,因为它会在任何时候甚至在一个操作的中间发生中断。

      代码示例:

    1. import java.util.concurrent.TimeUnit;  
    2. /** 
    3. * 守护线程 
    4. */ 
    5. public class Daemons {  
    6. /** 
    7. * @param args 
    8. * @throws InterruptedException  
    9. */ 
    10. public static void main(String[] args) throws InterruptedException {  
    11. Thread d = new Thread(new Daemon());  
    12. d.setDaemon(true); //必须在启动线程前调用 
    13. d.start();  
    14. System.out.println("d.isDaemon() = " + d.isDaemon() + ".");  
    15. TimeUnit.SECONDS.sleep(1);  
    16. }  
    17. }  
    18. class DaemonSpawn implements Runnable {  
    19. public void run() {  
    20. while (true) {  
    21. Thread.yield();  
    22. }  
    23. }  
    24. }  
    25. class Daemon implements Runnable {  
    26. private Thread[] t = new Thread[10];  
    27. public void run() {  
    28. for (int i=0; i<t.length; i++) {  
    29. t[i] = new Thread(new DaemonSpawn());  
    30. t[i].start();  
    31. System.out.println("DaemonSpawn " + i + " started.");  
    32. }  
    33. for (int i=0; i<t.length; i++) {  
    34. System.out.println("t[" + i + "].isDaemon() = " +  
    35. t[i].isDaemon() + ".");  
    36. }  
    37. while (true) {  
    38. Thread.yield();  
    39. }  
    40. }  
    41. }

      运行结果:

    1. d.isDaemon() = true.  
    2. DaemonSpawn 0 started.  
    3. DaemonSpawn 1 started.  
    4. DaemonSpawn 2 started.  
    5. DaemonSpawn 3 started.  
    6. DaemonSpawn 4 started.  
    7. DaemonSpawn 5 started.  
    8. DaemonSpawn 6 started.  
    9. DaemonSpawn 7 started.  
    10. DaemonSpawn 8 started.  
    11. DaemonSpawn 9 started.  
    12. t[0].isDaemon() = true.  
    13. t[1].isDaemon() = true.  
    14. t[2].isDaemon() = true.  
    15. t[3].isDaemon() = true.  
    16. t[4].isDaemon() = true.  
    17. t[5].isDaemon() = true.  
    18. t[6].isDaemon() = true.  
    19. t[7].isDaemon() = true.  
    20. t[8].isDaemon() = true.  
    21. t[9].isDaemon() = true.

     以上结果说明了守护线程中产生的新线程也是守护线程。

      如果将mian函数中的TimeUnit.SECONDS.sleep(1);注释掉,运行结果如下:

    1. d.isDaemon() = true.  
    2. DaemonSpawn 0 started.  
    3. DaemonSpawn 1 started.  
    4. DaemonSpawn 2 started.  
    5. DaemonSpawn 3 started.  
    6. DaemonSpawn 4 started.  
    7. DaemonSpawn 5 started.  
    8. DaemonSpawn 6 started.  
    9. DaemonSpawn 7 started.  
    10. DaemonSpawn 8 started.  
    11. DaemonSpawn 9 started.

      以上结果说明了如果用户线程已经全部退出运行了,只剩下守护线程存在了,虚拟机也就退出了。下面的例子也说明了这个问题。

      代码示例:

    1. import java.util.concurrent.TimeUnit;  
    2. /**  
    3. * Finally shoud be always run ?  
    4. */  
    5. public class DaemonsDontRunFinally {  
    6. /**  
    7. * @param args  
    8. */  
    9. public static void main(String[] args) {  
    10. Thread t = new Thread(new ADaemon());  
    11. t.setDaemon(true);  
    12. t.start();  
    13. }  
    14. }  
    15. class ADaemon implements Runnable {  
    16. public void run() {  
    17. try {  
    18. System.out.println("start ADaemon...");  
    19. TimeUnit.SECONDS.sleep(1);  
    20. } catch (InterruptedException e) {  
    21. System.out.println("Exiting via InterruptedException");  
    22. } finally {  
    23. System.out.println("This shoud be always run ?");  
    24. }  
    25. }  
    26. }

      运行结果:

      start ADaemon...

      如果将main函数中的t.setDaemon(true);注释掉,运行结果如下:

      start ADaemon...

      This shoud be always run ?



    posted @ 2011-12-31 10:34 顺其自然EVO 阅读(197) | 评论 (0)编辑 收藏

    五种方法教你搭建Linux学习环境(三)

      前两篇文章中已经介绍了三种搭建Linux学习环境的方法,本文将介绍第四、第五种方法。

      第四种方法:在Windows系统中,用VNC工具软件登录到远程服务器上的 Linux桌面。这种远程登录的方式,一方面可以用于远程配置和维护Linux服务器,另一方面也可以用它来在真实的环境中学习各种Linux命令。 VNC(Virtual Network Computing,虚拟网络计算机)软件主要由两部分组成,VNC server和VNC viewer。用户要先将VNC server安装在被控端的计算机上才能在主控端执行VNC viewer控制被控端。

      VNC server与VNC viewer支持多种操作系统,如Unix、Linux、Solaris、Windows和MacOS,因此可将VNC server 及VNC viewer分别安装在不同的操作系统中进行控制。如果目前操作的主控端计算机没有安装VNC viewer,也可以通过一般的网页浏览器来控制被控端。VNC的主要工作原理是在服务器端运行 VNC server服务,然后在客户端就可以远程连接服务器端的桌面了。下面就介绍,在主控端的计算机操作系统为Win 7,被控端服务器的操作系统为64位RedHat Enterprise Linux 5.3上的VNC viewer与VNC server的安装与配置步骤:

      1、在服务器端的RedHat中安装VNC server,安装包的文件名为“vnc-4.1.2-14.el5.x86_64.rpm”,此文件在光盘中的路径为“RedHat Enterprise Linux 5.3 for 64-bit AMD64 AND INTEL 64_Installation\Server”。

      也可以打开网站http://rpm.pbone.net/,在如下所示的对话框中输入“vnc-4.1.2-14.el5”,然后点击SEARCH,也可以找到相应的RPM安装包,下载下来即可,如图9所示。

    图9 下载RPM包网站图示

      2、安装VNC server的rpm包。可以把安装包“vnc-4.1.2-14.el5.x86_64.rpm”拷贝到\root\.vnc目录下,然后在此目录下直接运行安装命令即可,安装过程的显示提示如下所示:

      [root@localhost .vnc]# rpm -ivh vnc-4.1.2-14.el5.x86_64.rpm

      warning: vnc-4.1.2-14.el5.x86_64.rpm: Header V3 DSA signature: NOKEY, key ID 37017186

      Preparing...  ########################################### [100%]

      package vnc-4.1.2-14.el5.x86_64 is already installed

      3、编辑.vnc目录下的xstartup文件。可以使用vi编辑器进行编辑,命令为“[root@localhost .vnc]#vi xstartup”,打开xstartup文件后在键盘上点击“A”字母键,使VI编辑器进入编辑状态。然后屏蔽掉最后一行,即在最后一行的前面加上符号 “#”,变成“#twm &”,然后再在最下面加上“gnome-session &”。完成后,点击“Esc”键,再点击“:”键,然后输入“wq”回车,即保存退出。加上“gnome-session &”是为了能够在Windows系统上显示Linxu的桌面,否则只能看到一个“终端”的命令行窗口。

      4、设置登录用户。如果上面的安装成功,在目录/etc/sysconfig/下会有一个vncservers文件。用VI编辑器编辑vncservers文件,在最后加上VNCSERVERS="1:root",保存后退出。

      5、设置VNC远程登录密码。运行命令“[root@localhost ~]# vncpasswd”,然后按提示设置好远程登录的密码。然后执行命令“[root@localhost ~]#vncserver”,会有如下显示:

      New 'localhost.localdomain:1 (root)' desktop is localhost.localdomain:1

      Starting applications specified in /root/.vnc/xstartup

      Log file is /root/.vnc/localhost.localdomain:1.log

    这里需要注意的是,上面的输出“localhost.localdomain:1 (root)”,说明在用浏览器远程登录Linux系统时,在浏览器地址栏中要输入的地址为“Linux服务器的IP地址:5801”,如果上面的输出为 “2(root)”,则在浏览器地址栏中要输入的命令就为“5802”。如果连接成功,输入密码后就可以远程控制Linux桌面了。

    图10 用VNC Viewer软件登录的界面图示

      6、用浏览器登录Linux桌面的画质可能不太好,可以在Windows下安装VNC Viewer工具软件直接连接。首先要在Windows系统中安装RealVNC软件,如“vnc-4.1.3-x86_win32.exe”。安装完成后,打开“开始”菜单里的RealVNC ---> VNC Viewer 4 ---> Run VNC Viewer,在VNC Viewer的地址栏中输入“Linux服务器的IP地址:1”,如果上面的输出为“2”,则在VNC Viewer的地址栏中的IP地址后面把“:1”换成“:2”,如图10所示,点击“OK”,然后输入在上面“5”中设置的密码,就可成功连接到远程 Linux桌面,犹如在本地操作Linux系统一样,如图11所示。

    图11 用VNC Viewer远程登录到Linux桌面图示

      若在VNC Viewer的“Server”地址栏中输入的IP地址后面所接的端口号,不是“localhost.localdomain:1 (root)”中的“1”,而是写成了其它的数字,那可能只能进入到Linux系统的终端命令行模式,而进入不到图形化的桌面模式。

      下面将介绍第五种:用SSH方式登录到远程服务器的Linux系统中。其实和SSH登录方式非常相像的还有Telnet登录,但因为Telnet登录的用户名和密码,以及在配置管理当中所使用的Linux命令,都是以明文方式传送,没有任何安全措施,所以目前它基本上已经被SSH的登录方式所取代。SSH服务在Linux下的设置非常简单。下面就简要地介绍下SSH服务的设置与登录的步骤:

      1、SSH服务的安装状态。此服务默认是安装的,但也可以通过以下命令来查询在Linux系统中是否安装了SSH服务。

      [root@localhost ~]# rpm -qa | grep ssh

      openssh-clients-4.3p2-29.el5

      openssh-4.3p2-29.el5

      openssh-askpass-4.3p2-29.el5

      openssh-server-4.3p2-29.el5

      若出现以上的显示结果,则表示此Linux系统已经安装了SSH服务。输出内容的第一行显示的是SSH的客户端软件包;第二行显示的是SSH的核心文件;第三行表示SSH支持对话框的显示,是一个基于X系统的密码诊断工具;第四行是SSH的服务器软件包。

    2、SSH服务的运行状态。此服务默认也是自动运行的,但也可以通过以下命令来查询SSH服务的运行状态。

      [root@localhost ~]#service sshd status

      openssh-daemon (pid  5340) is running...

      若出现以上的显示结果,则表示此Linux系统的SSH服务已经运行。其中,“sshd”是SSH服务的守护进程名称。若SSH服务没有启动的话,则运行命令[root@localhost ~]#service sshd restart即可。

    图12 用SecureCRT以SSH方式登录的参数设置

      3、用SSH进行远程登录的设置。若是在Windows系统中,没有自带的SSH客户端,可以在网上下载支持SSH远程登录的图形化工具软件,常用的有 SecureCRT、Putty等。如图12所示,是用SecureCRT进行远程SSH登录的设置。在“Hostname”中输入SSH服务器的IP地址,“Port”中输入22,“Username”中输入用户名。然后根据提示,输入密码,就可以连接到远程的SSH服务器。若是在Linux系统中进行远程的SSH登录,就可以在Linux的终端窗口的命令提示符下,直接使用命令#ssh 192.168.1.2进行远程登录即可。

      4、SSH的配置文件。SSH有两个主要的配置文件,一个为客户端的配置文件ssh_config,一个为服务器端的配置文件sshd_config。这两个配置文件都位于目录/etc/ssh下。用VI编辑器就可以对这两个配置文件进行详细的配置和修改,以便用户在使用SSH时能满足一些特殊的要求。

      总结

      以上五种搭建Linux学习环境的模式,主要是根据实际情况,选择最适合自己的,它们之间无好坏之分。通常Linux高手对Linux的架构、命令都很熟悉,更习惯使用SSH的方式。这种方式在配置和管理服务器时更灵活,功能更强大。而对于网速带宽有保证的地方,同时又有充足的硬件服务器资源的话,采用第一种模式是最好的。

      第二种和第三种模式主要适用有个人固定的笔记本或台式机电脑,但网络带宽却不能保证的用户。这时,在个人电脑或虚拟机上安装Linux,也是不错的选择。第四种和第一种有相似之处,都要求网络带宽要有保证,但第四种没有第一种使用起来更方便。第四种还必须在电脑上安装RealVNC软件才行,若不安装的话使用浏览器和JAVA程序控制远程的Linux,效果并不是很好。

    相关链接:

    五种方法教你搭建Linux学习环境(一)

    五种方法教你搭建Linux学习环境(二)

    posted @ 2011-12-31 00:18 顺其自然EVO 阅读(552) | 评论 (0)编辑 收藏

    SQL Server的“警报”问题应该如何解决

    问:SQL Server的警报问题应该如何解决?

      答:具体的解决方法请参考下文 :

      ◆ 检查你是否使用了最新的Sql Server service pack。因为在最新的Sql Server service pack中已经修补了很多Sql Server使用警告(Alerts)的漏洞。应该确保在你的系统中已经安装了最新的Sql Server service pack补丁包。

      ◆ 检查SqlServerAgent服务的帐户是否作为成员运行在域用户群组(Domain User Group)下。LocalSystem帐户没有访问网络的权限,所以,如果你需要将事件记录在其他运行有Windows NT或Windows 2000机器上的应用程序日志上,或者你的作业(jobs)需要跨网络的资源,或者你需要通过e-mail或者pagers通知操作者,这时候,你就需要将SalServerAgent服务的帐户设置在域用户群组(Domain User Group)下作为它的成员。

      ◆ 如果所定义的警报都没有触发,检查SqlServerAgent和EventLog服务是否都在运行。如果你需要让你定义的警报被触发,这些服务必须被开启。所以,如果这些服务没有被运行的话,请运行它们。

      ◆ 如果有某个警报没有被触发,请确保它们是否被启用。警报可以被启用或禁用,为了检查一个警报是否被启用,你应该做以下这些步骤:

      1、运行Sql Server Enterprise Manager

      2、请打开服务器群组,然后打开某个服务器

      3、请打开管理(Management),然后再打开Sql Server Agent

      4、双击合适的警报以查看这个警报是否被启用了

      5、检查警报的历史值以确定警报最后工作的日期和时间

      为了检查一个警报的历史值,你应该做以下这些事情:

      1、运行Sql Server Enterprise Manager

      2、请打开服务器群组,然后打开某个服务器

      3、请打开管理(Management),然后再打开Sql Server Agent

      4、双击合适的警报以查看警报的历史值

      5、核对每20秒维护的计数器值

      因为Sql Server Agent每20秒间隔维护一个性能计数器,如果发现这个性能计数器只有几秒钟(少于20秒)才维护一次,那么极有可能你的这个警报将不会被触发。

      6、检查Sql Server错误日志、Sql Server Agent错误日志以及Windows NT和Windows 2000的应用程序日志,以获得有关错误描述的更多详细信息。仔细检查核对当产生警报失败事件时,被记录在Sql Server错误日志、Sql Server Agent错误日志以及Windows NT和Windows 2000的应用程序日志中的日期和时间以及对错误的描述能帮助你分析产生警报失败事件的原因。

      7、假如警报被触发了,但是这时候操作员却没有收到任何通知,请尝试手动使用“e-mail”,“pager”或者用“net send”将信息发送给操作员。在很多情况下,可能你输入了一个错%C。

    posted @ 2011-12-31 00:16 顺其自然EVO 阅读(170) | 评论 (0)编辑 收藏

    深入Java虚拟机之虚拟机体系结构

     工作以来,代码越写越多,程序也越来越臃肿,效率越来越低,对于我这样一个追求完美的程序员来说,这是绝对不被允许的,于是除了不断优化程序结构外,内存优化和性能调优就成了我惯用的“伎俩”。

      要对Java程序进行内存优化和性能调优,不了解虚拟机的内部原理(或者叫规范更严谨一点)是肯定不行的,这里推荐一本好书《深入Java虚拟机(第二版)》(Bill Venners著,曹晓刚 蒋靖 译,实际上本文正是作者阅读本书之后,对Java虚拟机的个人理解阐述)。当然了,了解Java虚拟机的好处并不仅限于上述两点好处。从更深一点的技术层面上看,了解Java虚拟机的规范和实现,将更加有助于我们编写高效、稳定的Java代码。比如,假如了解Java虚拟机的内存模型,了解虚拟机的内存回收机制,那么我们就不会过分依赖它,而会在需要的时候显式的"释放内存"(Java代码不能显式释放内存,但是可以通过释放对象引用告知垃圾回收器回收该对象需要被回收),以降低不必要的内存消耗;假如我们了解Java栈的工作原理,那么我们就可以通过减少递归层数,减少循环次数来降低堆栈溢出的风险。可能对于应用开发人员来说,可能不会直接去涉及这些Java虚拟机底层实现的工作,但是了解这些背景知识,或多或少,都会对我们写的程序产生潜移默化的好的影响。

      本篇文章,将简明扼要的说明Java虚拟机的体系结构和内存模型,如有用词不妥或解释不准确之处,请不吝指正,深感荣幸!

      Java 虚拟机体系结构

      类装载子系统

      Java虚拟机有两种类装载器,分别是启动类装载器和用户自定义装载器。

      通类装载子系统通过类的全限定名(包名和类名,网络装载还包括 URL)将 Class 装载进运行时数据区。对于每一个被装载的类型,Java虚拟机都会创建一个java.lang.Class类的实例来代表该类型,该实例被放在内存中的堆区,而装载的类型信息则位于方法区,这一点和所有其他对象都是一样的。

      类装载子系统在装载一个类型前,除了要定位和导入对应的二进制class文件外,还要验证导入类的正确性,为类变量分配并初始化内存,以及解析符号引用为直接引用,这些动作严格按照以下顺序进行:

      1)装载——查找并装载类型的二进制数据;

      2)连接——执行验证,准备以及解析(可选)

      3)验证 确保被导入类型的正确性

      4)准备 为类变量分配内存,并将其初始化为默认值

      5)解析 把类型中的符号引用转换为直接应用

      方法区

      对于每一个被类装载子系统装载的类型,虚拟机都会保存下列数据到方法区:

      ◆  类型的全限定名

      ◆ 类型超类的全限定名(java.lang.Object没有超类)

      ◆ 类型是类类型还是接口类型

      ◆ 类型的访问修饰符

      ◆ 任何直接超接口的全限定名有序列表

     除了上述基本类型信息,还将保存如下信息:

      ◆ 类型的常量池

      ◆ 字段信息(包括字段名、字段类型、字段修饰符)

      ◆ 方法信息(包括方法名、返回类型、参数的数量和类型、方法修饰符,如果方法不是抽象和本地的,还将保存方法的字节码、操作数栈和该方法栈帧中的局部变量区的大小和异常表)

      ◆ 常量以外的所有类变量(其实就是类的静态变量,因为静态变量是所有实例共享的,且与类型直接相关,所以他们是类一级的变量,作为类的成员被保存在方法区)

      一个到类ClassLoader的引用

  • //返回的就是刚才保存的ClassLoader引用   
  • String.class.getClassLoader();
  •   一个到Class类的引用

  • //将返回刚才保存的Class类的引用   
  • String.class;
  •   注意,方法区也是可以被垃圾回收器回收的。

      堆

      Java程序在运行时创建的所有类实例或数组都放在同一个堆中,而每一个Java虚拟机也是有一个对空间,所有线程共享一个堆(这就是一个多线程的Java程序会产生对象访问的同步问题的原因了)。

      由于每一种Java虚拟机都有对虚拟机规范的不同实现,所以我们可能不知道每一种Java虚拟机在堆中是以何种形式表示对象实例的,不过我们可以通过下面这可能的实现来一窥端倪:


      程序计数器

      对于运行中的Java程序而言,每一个线程都有自己的PC(程序计数器)寄存器,它是在该线程启动时创建的,大小为一个字长,用来保存需要被执行的下一行代码的位置。

      Java栈

      每一个线程都有一个Java栈,以栈帧为单位保存线程的运行状态。虚拟机对Java栈的操作有两种:压栈和出栈,二者都已帧为单位。栈帧保存了传入参数、局部变量、中间运算结果等数据,在方法完成时被弹出,然后释放。

      看一下两个局部变量相加时栈帧的内存快照

      本地方法栈

      这是 Java 调用操作系统本地库的地方,用来实现 JNI(Java Native Interface,Java 本地接口)

      执行引擎

      Java虚拟机的核心,控制装入 Java 字节码并解析;对于运行中的Java程序而言,每一个线程都是一个独立的虚拟机执行引擎的实例,从线程生命周期的开始到结束,他要么在执行字节码,要么在执行本地方法。

      本地接口

      连接了本地方法栈和操作系统库。

      注:文中所有提到“Java虚拟机”的地方都是指“JavaEE和JavaSE平台的Java虚拟机规范”。

    posted @ 2011-12-31 00:15 顺其自然EVO 阅读(171) | 评论 (0)编辑 收藏

    从Java的角度理解Ext的extend

         摘要: 在Java中,我们在实现继承的时候存在下面几个事实:  1、准备两个类,他们用extends关键字链接起来  2、如果超类没有默认构造函数,需要在子类构造函数中显式的super并传参,如果都是默认构造函数也可以super,不super虚拟机是自动的  3、子类可追加,覆盖,重载方法,子类可以有自己的私有属性,他们在子类构造函数中被构造  4、字段是数据,方法在代码区,和类建立方法表,同一个类的对象...  阅读全文

    posted @ 2011-12-29 13:26 顺其自然EVO 阅读(199) | 评论 (0)编辑 收藏

    组织beta测试的十二个最高秘诀

    组织beta测试的十二个最高秘诀

     这篇文章中,作者以诚恳的笔触将自己在组织beta测试的亲身感受与大家分享,希望可以给广大开发人员带来帮助。

      下面是一些关于如何组织一次软件的beta测试的秘诀。需要注意的是,这里所说的“软件”指的是面向大量用户的软件,也就是我所称的“包装盒软件(注:“包装盒软件”指的是在商场中上架销售、有独立包装、外面用热收缩塑料膜密封的软件商品。)”(shrink-wrap)。这些秘诀对商业项目和开源项目都适用。不管你开发软件的目的是获得报酬,还是获得眼球效应,或是提高在同行中的知名度,都可以参考这些秘诀。但是,我关注的只是有大量用户的软件产品,而不是公司内部的IT项目。

      1. 开放式的beta测试是没用的。要是你那样做,只可能有两种结果。一种结果是你有太多的测试者(就像Netscape那样),这些人向你反馈了大量的意见,你从中根本不可能得到有用的数据。另一种结果是,现有的测试者根本不向你反馈他们的使用情况,导致你无法得到足够的数据。

      2. 要想找到那些能够向你反馈意见的测试者,最好的方法是诉诸他们“言行一致”的心理。你需要让他们自己承诺会向你发送反馈意见,或者更好的方法是,让他们自己申请参加beta测试。一旦他们采取了某些主动行为,比如填写一张申请表,在“我同意尽快发回反馈意见和软件故障报告”的选项上打勾,许多人就会发送反馈意见,因为他们想要“言行一致”。

      3. 不要妄想一次完整的beta测试的所有步骤能够在少于8-10周的时间内完成。我曾经试过,结果是除非老天帮忙,否则根本不可能做到。

      4. 不要妄想在测试中发布新的软件版本的频率能够快于每两周一次。我曾经试过,结果是除非老天帮忙,否则根本不可能有效。

      5. 一次beta测试中计划发布的软件版本不要少于4个。我从来没试过少于4个版本,因为太明显了,那样不可能达到测试目的。

      6. 如果在测试过程中你为软件添加了一个功能,那么哪怕这个功能非常微小,整个8个星期的测试也要回到起点,从头来过,而且你还需要再发布3个或4个新版本。我犯过的最大错误之一就是,在CityDesk 2.0的beta测试接近尾声的时候,我向软件中加入了一些保留空格的代码,这产生了一些意想不到的副作用(如果我们可以这样说),测试的时间不够了,我本应该将测试时间加长、进一步收集数据的。

      7. 即使你有一个申请参加beta测试的步骤,最后也只有五分之一的测试者会向你提交反馈意见。

      8. 我们制定了一条政策,所有向我们提交反馈意见的测试者都将免费获赠一份正版软件。不管你的反馈意见是正面的,还是负面的,只要你提交给我们,就能获得赠品。但是,在测试结束的时候,那些不提交反馈意见的测试者什么也不会得到。

      9. 你需要的严肃测试者(即那些会把反馈意见写成3页纸发送给你的人)的最小数量大约是100人左右。如果你独立开发软件,那么这是你能够处理的反馈意见的最大数量。如果你有一支测试管理团队或专门的beta测试经理,那么设法分别为每个处理反馈意见的人找到100个严肃测试者。

      10. 根据第7条,即使你有一个参加beta测试的申请步骤,最后也只有五分之一的测试者会真地使用你的产品并将反馈意见发送给你。那么,假定你有一个质量控制部门,里面一共有3个测试管理人员,这就意味着你必须批准1500份参加beta测试的申请表,因为这样才能产生300个严肃测试者。批准的数量少于这个数目的话,你就不会得到充分的反馈意见;批准的数量多于这个数目的话,你就会被许许多多重复的反馈意见淹没。

      11. 大多数beta测试的参与者只是在第一次拿到这个程序的时候才会去试用一下,然后就丧失了兴趣。此后每次你推出一个新的版本并发送给他们,他们也不会有兴趣重新测试它。除非他们每天都在用这个程序,但是对于大多数人来说,这是不可能的。因此,你需要错开不同版本的测试对象,将你的所有beta测试参与者分成四组,每次发布一个新版本的时候,就把一个新的组加入测试,这样就能保证每个版本都有第一次使用这个程序的测试者。

      12. 不要混淆技术beta和市场beta。我上面谈的这些都是针对技术beta,它的目标是发现软件中的错误和得到及时的用户反馈意见。市场beta则是软件正式发布前的预览版本,对象主要是新闻媒体、大客户和那些写入门教程的家伙(该教程必须在软件上市的同一天问世)。对于市场beta,你的目的并不是得到反馈意见。(虽然无论你怎么做,那些写书的家伙很可能都会滔滔不绝地告诉你一大堆意见。如果你置之不理,这些意见就会被复制粘贴进他们自己的书里。)

    posted @ 2011-12-26 11:46 顺其自然EVO 阅读(158) | 评论 (0)编辑 收藏

    数据库加密领域的五个最差实践

    数据库加密领域的五个最差实践

     薄弱的加密措施让数据库关键信息面临更多风险。数据库加密对于关键数据的存储安全性有着巨大的意义,但这种积极意义产生的前提是首先将加密工作做好。随着数据库加密部署情况的日益增多,部署效果自然也随之变得良莠不齐。以下五类数据库加密部署是专家组们公认的最差实践方式。为了获得最理想的安全效益,我们应该尽量避免如下几类操作失误。

      1、将密钥保存在错误的地方

      据安全专家称,很多人习惯于将加密的数据和密钥一起存放,这称得上是数据库加密工作中的原罪之一。

      “如果你在你的数据库中加密敏感信息,那么千万不要把加密密钥或者认证证书同与之相关加密数据存储在一起。”电气行业首席安全工程师Luther Martin说道,“一旦发生这种情况,虽然感觉上加密信息是安全的,其实整套体系已经失去了实际意义。”

      若想真正地保护好数据,要将密钥妥善地加以管理;应把它与加密数据、敏感信息密钥之类,各自区分并存放。

      2、密钥未能集中管理

      由于很多企业自身的安保机制较为薄弱,因此随意将密钥保存在防范措施不足的地方也就比较常见。

      “关键问题在于在企业内部,使用大量密钥和数字签证的情况广泛存在”,Venafi的CEO Jeff Hudson说,“研究表明,企业中所管理的认证及密钥系统少则上千、多则上万的现象非常普遍。”

      很多厂商都销售加密产品,却没有向客户教授相应的管理应用知识,Hudson说。

      “加密技术只是解决方案的一半。IT部门必须掌握监控密钥并需要了解都谁有权使用密钥。为了维护整个企业的利益,快速为密钥部署妥善的保护机制可谓至关重要,”他说。“为了严格贯彻访问控制,职责分离以及策略改善制度,大家需要对自动化监控密钥和证书管理工作加深理解。”

      理论上,为了了解本地密钥在哪里以及保护这些密钥的具体方案,企业应当尽可能地集中管理密钥。

      3、依靠自创的方案

      IT人士最怕的就是客户自己搞出一套自创系统,借以节约成本。但他们的利己意识倒不一定是坏事,因为除非你的员工都是具有多年经验的密码专家,否则轻易使用自制的加密方案或者密钥管理系统简直就是自掘坟墓。

      “失败的自主开发数据库加密密钥管理方案的部署,会迫使那些主要经营零售业的厂商转型为专业型供应商” Protegrity公司的CTO Ulf Mattsson说:“这看起来非常容易但实际上相当危险。”

      4、缺乏备份资料加密机制

      如果你只对数据库进行加密,而不对相关数据的备份加以同样的保护,也会让你的企业陷入风险当中。

      “在我们生活的时代里,磁带落在后备厢里,笔记本丢了等等所有意外情况都不能成为我们的借口,” 403网络安全CEO Alan Wlasuk说“为所有数据库的备份资料进行加密是一件理所当然的事。”

      “即使表面上看来毫无价值,也要以00加密格式备份所有数据库内容,”他说“数据备份最终会存储在一个意想不到的地方,如果你知道他们是安全的,你也就可以高枕无忧了。”

      5、使用过时的加密算法

      在去年11月Gawker遭受的重创中,部分原因就是密码信息惨遭泄露,这些密码被几十年未更新过的陈旧加密技术保护着。而这一情况并非特例。许多企业都需要对数据进行加密,但使用的却是超级老旧的加密方式,这简直像是在用纸做的盔甲来保护自己的身体。

      “多年前使用的中古加密技术系统早就扛不住了” Wlasuk说。企业不仅仅要留心加密数据库,同样要关注哪些加密技术已经过时、并迫切需要新的加密算法补充进来。

    posted @ 2011-12-26 11:43 顺其自然EVO 阅读(175) | 评论 (0)编辑 收藏

    好用的清理数据库脚本

    1、脚本说明

      此脚本用于清空数据库数据,只删除相关表记录,保留表结构及存储过程触发器等主要架构。

      设计思路:

      1)根据表添加时间逆向获取所有用户表信息

      2)使用游标循环删除每张表内数据

      3)使用delete进行删除,即使有外键关系同样可以删除表记录

      4)表存在自增主键则将其重置为0

      5)截断日志,将数据库表空间及日志文件缩减到最小

      2、使用说明

      1)建立删除数据库存储过程SP_DaTaBaSeClear

    以下是代码片段:
    If( object_id('SP_DaTaBaSeClear') is not null ) drop procedure SP_DaTaBaSeClear go SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE PROCEDURE SP_DaTaBaSeClearASBegin Transaction declare @BtableName varchar(200) declare curDel cursor for select rtrim(name) from sysobjects where type = 'U' order by crdate desc open curDel declare @delSQL varchar(500) fetch next from curDel into @BtableName while( @@fetch_status = 0) begin set @delSQL = 'delete from ' + @BtableName print @delSQL exec( @delSQL ) if( ident_seed(@BtableName) is not null ) begin dbcc checkident( @BtableName, reseed, 0 ) print '种子成功置为1' end fetch next from curDel into @BtableName end close curDel deallocate curDel Commit GO

      2)执行该存储过程,执行过程中查看执行信息,如有红色信息则先手动删除红色信息表记录

      -- 执行存储过程删除表数据

      EXEC SP_DaTaBaSeClear

      3)如仍然报出红色信息则直接执行以下语句进行删除

    以下是代码片段:
    declare @BtableName varchar(128) declare curDel cursor for select rtrim(name) from sysobjects where type = 'U' order by crdate desc open curDel declare @delSQL varchar(255) fetch next from curDel into @BtableName while( @@fetch_status = 0) begin set @delSQL = 'delete from ' + @BtableName print @delSQL exec( @delSQL ) if( ident_seed(@BtableName) is not null ) begin dbcc checkident( @BtableName, reseed, 0 ) print '种子成功置为1' end fetch next from curDel into @BtableName end close curDel deallocate curDel

      4)最后执行脚本重置数据库大小

    以下是代码片段:
        backup log @DataBaseName with no_log dbccshrinkdatabase(@DataBaseName)
      dbccupdateusage(@DataBaseName)

    posted @ 2011-12-26 11:40 顺其自然EVO 阅读(235) | 评论 (0)编辑 收藏

    解读Java环境变量配置

    1、查看当前可用的所有环境变量(=系统变量+用户变量)

      set

      查看某个环境变量,如PATH

      set PATH

      添加环境变量,如xxx=aa

      set xxx=aa

      将环境变量(如xxx)的值置为空

      set xxx=

      在某个环境变量(如PATH)后添加新的值(如d:\xxx)

      set PATH=%PATH%;d:\xxx

      [注]:以命令行方式对环境变量的操作只对当前窗口的应用有效!

      2、WindowsJAVA用到的环境变量主要有3个:JAVA_HOME、CLASSPATH、PATH。

      1)JAVA_HOME指向的是JDK的安装路径,如x:\ j2sdk1.4.2,在这路径下你应该能够找到bin、lib等目录。设置方法:JAVA_HOME=c:\ j2sdk1.4.2

      2)PATH变量的作用

      java程序在运行时首先在path变量所定义的路径去找java.exe,并以最先找到的为准,如果安装完j2sdk后不加设置,一般是C:\WINDOWS\system32目录。

      j2sdk1.4(还有其它java开发工具如jbuilder8)在安装后会将java.exe拷贝到C:\WINDOWS\system32目录下,当执行java.exe时,需要装载这个SDK下的一些文件。

      如j2sdk1.4在安装完成后,C:\WINDOWS\system32下的java.exe在运行时会在C:\Program File\java\目录下装载必需的一些文件。但安装j2sdk后一般会在PATH变量的最前面设置C:\ j2sdk1.4.2 \bin。

      当先安装j2sdk1.4.2,后安装jbuilder8等开发工具时,由于jbuilder8的java.exe在拷贝到C:\WINDOWS\system32时可能覆盖了j2sdk1.4.2的java.exe,那么这时在运行的java.exe会到jbuilder8所在的目录去装载必需的一些文件。

      3)CLASSPATH环境变量的作用

      告诉类装载器到哪里去寻找第三方提供的类和用户定义的类。也可用使用JVM命令行参数-classpath分别为应用程序指定类路径,在-classpath中指定的类路径覆盖CLASSPATH环境变量中指定的值。

      3、当机器内装有多个SDK版本时,如何查看所用的是哪个SDK?

      java -verbose

      在出现的屏幕信息中可以看出系统装载的是哪个目录下的文件。

      4、Windows OS下设置PATH的方法

      〔系统〕->〔环境〕-> 〔高级〕,在PATH变量的文本框中的最前面输入C:\ j2sdk1.4.2\bin

      或在命令行窗口中执行 set path=c:\j2sdk1.4.2\bin;%path%; 这样在命令行窗口的任一路径下都可以执行java.exe程序了。或设置PATH=%JAVA_HOME%\bin;%PATH%

      5、对于CLASSPATH环境变量的设置方法要加倍小心,是因为以后你出现的莫名其妙80%以上的怪问题都可能是由于CLASSPATH设置不对引起的

      CLASSPATH=.\;%JAVA_HOME%\lib\tools.jar

      首先要注意的是最前面的".\;",——句点反斜杠分号。这个是告诉JDK,搜索CLASS时先查找当前目录的CLASS文件。

      【Troubleshooting】

      编译会出现以下情况,看你是否真得都理解环境变量的设置,并能解决它。

      [T1] error:java不是一个可运行的程序? 由于没有设置环境变量path

      [T2] error:不能打开某个目录? 可能是忽视了path环境变量中的目录的设置顺序。

      [T3] Exception on thread “main” java.lang.DoClassDefFoundError:Test?没有设置classpath的路径。

    posted @ 2011-12-26 11:39 顺其自然EVO 阅读(257) | 评论 (0)编辑 收藏

    仅列出标题
    共394页: First 上一页 345 346 347 348 349 350 351 352 353 下一页 Last 
    <2024年11月>
    272829303112
    3456789
    10111213141516
    17181920212223
    24252627282930
    1234567

    导航

    统计

    常用链接

    留言簿(55)

    随笔分类

    随笔档案

    文章分类

    文章档案

    搜索

    最新评论

    阅读排行榜

    评论排行榜