it-e-32 Introduction to DBMS

A database management system (DBMS) is an important type of programming system, used
today on the biggest and the smallest computers. [1]As for other major forms of system software,
such as compilers and operating systems, a well-understood set of principles for database
management systems has developed over the years, and these concepts are useful both for
understanding how to use these systems effectively and for designing and implementing DBMS's.
DBMS is a collection of programs that enables you to store, modify, and extract information
from a database. There are many different types of DBMS's, ranging from small systems that run
on personal computers to huge systems that run on mainframes. The following are the location of
database between application programs and end-users.

There are two qualities that distinguish database management systems from other sorts of
programming systems.
1) The ability to manage persistent data, and
2) The ability to access large amounts of data efficiently.

Point 1) merely states that there is a database which exists permanently; the contents of this
database is the data that a DBMS accesses and manages.

Point 2) distinguishes a DBMS from a
file system, which also manages persistent data. A DBMS's capabilities are needed most when
the amount of data is very large, because for small amounts of data, simple access techniques,
such as linear scans of the data, are usually adequate.
[2]While we regard the above two properties of a DBMS as fundamental, there are a number
of other capabilities that are almost universally found in commercial DBMS's. These are:
Support for at least one data model, or mathematical abstraction through which the user can
view the data.

Support for certain high-level languages that allow the user to define the structure of data,
access data, and manipulate data.
Transaction management, the capability to provide correct, concurrent access to the database
by many users at once.
Access control, the ability to limit access to data by unauthorized users, and the ability to
check the validity of data.
Resiliency, the ability to recover from system failures without losing data.
Data Models Each DBMS provides at least one abstract model of data that allows the user
to see information not as raw bits, but in more understandable terms. In fact, it is usually possible
to see data at several levels of abstraction. At a relatively low level, a DBMS commonly allows
us to visualize data as composed of files.
Efficient File Access The ability to store a file is not remarkable: the file system associated
with any operating system does that. The capability of a DBMS is seen when we access the data of
a file. For example, suppose we wish to find the manager of employee "Clark Kent". If the
company has thousands of employees, It is very expensive to search the entire file to find the one
with NAME="Clark Kent". A DBMS helps us to set up "index files," or "indices," that allow us to
access the record for "Clark Kent" in essentially one stroke no matter how large the file is. Likewise,
insertion of new records or deletion of old ones can be accomplished in time that is small and
essentially constant, independent of the file’s length. Another thing a DBMS helps us do is navigate
among files, that is, to combine values in two or more files to obtain the information we want.
Query Languages To make access to files easier, a DBMS provides a query language, or
data manipulation language, to express operations on files. Query languages differ in the level of
detail they require of the user, with systems based on the relational data model generally
requiring less detail than languages based on other models.

Transaction Management

Another important capability of a DBMS is the ability to
manage simultaneously large numbers of transactions, which are procedures operating on the
database. Some databases are so large that they can only be useful if they are operated upon
simultaneously by many computers: often these computers are dispersed around the country or
the world. The database systems used by banks, accessed almost instantaneously by hundreds or
thousands of automated teller machines (ATM), as well as by an equal or greater number of
employees in the bank branches, is typical of this sort of database. An airline reservation system
is another good example.
Sometimes, two accesses do not interfere with each other. For example, any number of
transactions can be reading your bank balance at the same time, without any inconsistency. [3]But
if you are in the bank depositing your salary check at the exact instant your spouse is extracting
money from an automatic teller, the result of the two transactions occurring simultaneously and
without coordination is unpredictable. Thus, transactions that modify a data item must “lock out”
other transactions trying to read or write that item at the same time. A DBMS must therefore
provide some form of concurrency control to prevent uncoordinated access to the same data item

by more than one transaction.
Even more complex problems occur when the database is distributed over many different
computer systems, perhaps with duplication of data to allow both faster local access and to
protect against the destruction of data if one computer crashes.
Security of Data A DBMS must not only protect against loss of data when crashes occur,
as we just mentioned, but it must prevent unauthorized access. For example, only users with a
certain clearance should have access to the salary field of an employee file, and the DBMS must
be able associate with the various users their privileges to see files, fields within files, or other
subsets of the data in the database. Thus a DBMS must maintain a table telling for each user
known to it, what access privileges the user has for each object. For example, one user may be
allowed to read a file, but not to insert or delete data; another may not be allowed to see the file at
all, while a third may be allowed to read or modify the file at will.

DBMS Types
Designers developed three different types of database structures: hierarchical, network, and
relational. Hierarchical and network were first developed but relational has become dominant.
While the relational design is dominant, the older databases have not been dropped. Companies
that installed a hierarchical system such as IMS in the 1970s will be using and maintaining these
databases for years to come even though new development is being done on relational systems.
These older systems are often referred to as legacy systems.

1, teller  ['telə]
n. (美)出纳员;讲述者;讲故事者;计票员

2, reservation  [,rezə'veiʃən]
n. 预约,预订;保留
3, at will 
随意;任意

Continue reading it-e-32 Introduction to DBMS

业务用例与系统用例的区别

  • 一个业务用例描述的是业务过程——而不是软件系统过程。
  • 一个业务用例为涉众创造价值。这些涉众要么是业务参与者要么是业务工作者。
  • 一个业务用例可以超越组织的边界。有些构架师对于这一点有非常严密的态度。许多业务用例确实超越来组织的边界,但是有些业务用例仅仅关注于一个组织。

 

  • 1.业务用例就是要完成的业务,系统用例是系统要做的事情,两者的域不同。
  • 2.业务建模主要描述了该项目涉及的所有业务,需求模型主要是描述为了满足业务需求系统要做什么,因此,需求模型与业务模型相比,它描述的只是业务模型的一个子集。
  • 3.比方说我们设计一个自动提款机系统,它可以满足用户的取款、改密、查询等需求,那么这些需求就是业务用例;但是用户又分为借记卡用户和信用卡用户,那么根据业务规则,不同的卡用户的取款、改密、查询的过程是不一样的,所以系统为了满足这种业务需求会包含到两个子用例里实现,这种子用例就是系统用例。也就是说系统用例就是系统为了满足这种业务需求要做什么。

 

为什么要区别这些?可能在你的用例图中就混杂了这两种用例。

 

 

参见:

http://www.uml.org.cn/requirementproject/200707024.asp

http://gaojiewyh.iteye.com/blog/408363

http://www.cnblogs.com/rhcad/archive/2010/06/11/1756173.html

Continue reading 业务用例与系统用例的区别

it-e-31 Steganography and Honeytokens

Steganography is a method of embedding electronic messages into a media file (for example, an image or audio file) by altering nonessential lines of code; the changes are imperceptible. The message remains undetected until unencrypted. Honeytokens is any kind of tantalizing false data, including phony patient records at a hospital, lists of invalid social security numbersor even simply a word processing file named "HR-salaries," that's stored in a restricted part of the network. If anyone tries to access the files the security team is alerted to the trespassing before the intruder can do any real damage.

1, imperceptible  [,impə'septəbl]
a. 不能感知的,不知不觉的,微细的

2, steganography  [,stegə'nɔgrəfi]
n. 速记式加密
3, tantalizing  ['tæntəlaiziŋ]
a. 诱人的
4, phony  ['fəuni]
a. 假的,伪造的
5, trespassing 
n. 擅自进入
v. 侵入;犯罪(trespass的ing形式)
6, intruder  [in'tru:də]
n. 侵入者,干扰者,妨碍者

Continue reading it-e-31 Steganography and Honeytokens

ServiceMix环境配置

 

配置使用的ServiceMix版本是servicemix-3.3tomcat5.5以上运行(因为依赖包大部分是需要jdk1.5)

ServiceMix有三种部署方式:单独程序方式,servlet方式,Geronimo and JBoss.整合方式。这里主要介绍servlet方式,因为这样可以整合到任何servlet容器中。

Servlet部署需要在web.xml中配置spring加载文件,这种spring是和xbean整合的自定义配置文件。

 

配置文件说明:

Web.xml

 

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE web-app

    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"

    "http://java.sun.com/dtd/web-app_2_3.dtd">

 

<web-app>

  <display-name>ServiceMix Web Application</display-name>

  <description>Deploys ServiceMix inside a Web Application</description>

 

  <context-param>

    <param-name>contextConfigLocation</param-name>

    <param-value>/WEB-INF/jmx.xml /WEB-INF/core.xml /WEB-INF/activemq.xml</param-value>

  </context-param>

Spring配置文件

  <context-param>

    <param-name>contextClass</param-name>

    <param-value>org.apache.xbean.spring.context.XmlWebApplicationContext</param-value>

  </context-param>

 

  <listener>

    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

  </listener>

Spring 监听器

  <!-- servlet mappings -->

 

  <!-- the main JMX servlet -->

  <servlet>

    <servlet-name>JMXServlet</servlet-name>

    <servlet-class>org.apache.servicemix.web.jmx.JMXServlet</servlet-class>

    <load-on-startup>1</load-on-startup>

  </servlet>

 

  <!--  the HTTP binding servlet -->

 

  <!-- START SNIPPET: servicemix-http-->

  <servlet>

    <servlet-name>HttpManagedServlet</servlet-name>

    <servlet-class>

      org.apache.servicemix.http.HttpManagedServlet

    </servlet-class>

    <load-on-startup>1</load-on-startup>

  </servlet>

http bean组件(BC)servlet

  <servlet-mapping>

    <servlet-name>HttpManagedServlet</servlet-name>

    <url-pattern>/jbi/*</url-pattern>

  </servlet-mapping>

 

  <!-- END SNIPPET: httpBinding -->

 

  <servlet-mapping>

    <servlet-name>JMXServlet</servlet-name>

    <url-pattern>/jmx/*</url-pattern>

  </servlet-mapping>

 

</web-app>

 

demo主要功能的配置在core.xml:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns:sm="http://servicemix.apache.org/config/1.0"

       xmlns:http="http://servicemix.apache.org/http/1.0"

                   xmlns:my="http://servicemix.apache.org/demo/"

       xmlns:foo="http://servicemix.apache.org/demo/">

 

  <!-- the JBI container -->

  <sm:container id="jbi"

      rootDir="#rootDir"

      useMBeanServer="true"

                              createMBeanServer="false"

      MBeanServer="#jmxServer"

      installationDirPath="#installDir"

      deploymentDirPath="#deployDir"

                              monitorInstallationDirectory="true"

      transactionManager="#transactionManager"

      depends-on="broker">

 

    <sm:activationSpecs>

 

      <!--  an example HTTP binding for use by the SpringBindingServlet  -->

      <!-- START SNIPPET: http -->

      <sm:activationSpec componentName="servicemix-http" service="foo:httpBinding" destinationService="foo:echo">

        <sm:component>

          <http:component>

            <http:configuration managed="true" />

            <http:endpoints>

              <http:endpoint service="foo:httpBinding"

                             endpoint="endpoint"

                             targetService="foo:echo"

                             role="consumer"

                             locationURI="http://localhost/exampleUri/

配置url, 会被tomcat自动转换为serverapp/jbi/ exampleUri

"

                             defaultMep="http://www.w3.org/2004/08/wsdl/in-out

消息请求方式是in-out,即期望又返回消息

" />

            </http:endpoints>

          </http:component>

        </sm:component>

      </sm:activationSpec>

使用http BC,作为一个消费者(consumer)目标指向服务引擎(SE)foo:echo

      <!-- END SNIPPET: http -->

 

      <!--  a simple Echo service to test InOut message exchanges using HTTP-->

      <sm:activationSpec componentName="echo" service="foo:echo" >

        <sm:component>

          <bean class="org.apache.servicemix.components.HelloWorldComponent">

            <property name="property" value="name"/>

          </bean>

        </sm:component>

      </sm:activationSpec>

SE foo:echo,这是一个简单的helloworld

</beans>

 

经过这样的配置和在web.xml中配置的servlet,那么uri pattern形如 /jbi/exampleUri请求foo:httpBinding (BC),在ESB内部foo:httpBinding通过消息路由(normalized message router)foo:echo通信

Web测试页面链接为http://localhost:(tomcat端口)/ESB-ServerMix-Web/examples/

 

需要在firefox下测试。

测试页面使用ajax请求/jbi/exampleUri经过foo:httpBinding, foo:echo处理返回信息。

 

 

Continue reading ServiceMix环境配置

【转】几种常见的网络存储技术的比较研究

随着计算网络技术的飞速发展,各种网络服务器对存储的需求随之发展,但由于商业企业规模不同,对网络存储的需求也应有所不同,选择不当的网络存储技术,往往会使得企业在网络建设中盲目投资不需要的设备,或者造成企业的网络性能低下,影响企业信息化发展,因此商业企业如何选择和使用适当的专业存储方式是非常重要的。 
目前高端服务器所使用的专业存储方案有DAS、NAS、SAN、iscsl几种,通过这几种专业的存储方案使用RAID阵列提供的高效安全的存储空间。 
一、直接附加存储(DAS) 
直接附加存储是指将存储设备通过SCSI接口直接连接到一台服务器上使用。DAS购置成本低,配置简单,使用过程和使用本机硬盘并无太大差别,对于服务器的要求仅仅是一个外接的SCSI口,因此对于小型企业很有吸引力。但是DAS也存在诸多问题:(1)服务器本身容易成为系统瓶颈;(2)服务器发生故障,数据不可访问;(3)对于存在多个服务器的系统来说,设备分散,不便管理。同时多台服务器使用DAS时,存储空间不能在服务器之间动态分配,可能造成相当的资源浪费;(4)数据备份操作复杂。 
二、网络附加存储(NAS) 
NAS实际是一种带有瘦服务器的存储设备。这个瘦服务器实际是一台网络文件服务器。NAS设备直接连接到TCP/IP网络上,网络服务器通过TCP/IP网络存取管理数据。NAS作为一种瘦服务器系统,易于安装和部署,管理使用也很方便。同时由于可以允许客户机不通过服务器直接在NAS中存取数据,因此对服务器来说可以减少系统开销。NAS为异构平台使用统一存储系统提供了解决方案。由于NAS只需要在一个基本的磁盘阵列柜外增加一套瘦服务器系统,对硬件要求很低,软件成本也不高,甚至可以使用免费的LINUX解决方案,成本只比直接附加存储略高。NAS存在的主要问题是:(1)由于存储数据通过普通数据网络传输,因此易受网络上其它流量的影响。当网络上有其它大数据流量时会严重影响系统性能;(2)由于存储数据通过普通数据网络传输,因此容易产生数据泄漏等安全问题;(3)存储只能以文件方式访问,而不能像普通文件系统一样直接访问物理数据块,因此会在某些情况下严重影响系统效率,比如大型数据库就不能使用NAS。 
三、存储区域网(SAN) 
SAN实际是一种专门为存储建立的独立于TCP/IP网络之外的专用网络。目前一般的SAN提供2Gb/S到4Gb/S的传输数率,同时SAN网络独立于数据网络存在,因此存取速度很快,另外SAN一般采用高端的RAID阵列,使SAN的性能在几种专业存储方案中傲视群雄。SAN由于其基础是一个专用网络,因此扩展性很强,不管是在一个SAN系统中增加一定的存储空间还是增加几台使用存储空间的服务器都非常方便。通过SAN接口的磁带机,SAN系统可以方便高效的实现数据的集中备份。SAN作为一种新兴的存储方式,是未来存储技术的发展方向,但是,它也存在一些缺点:(1)价格昂贵。不论是SAN阵列柜还是SAN必须的光纤通道交换机价格都是十分昂贵的,就连服务器上使用的光通道卡的价格也是不容易被小型商业企业所接受的;(2)需要单独建立光纤网络,异地扩展比较困难;

四、iSCSI 
使用专门的存储区域网成本很高,而利用普通的数据网来传输SCSI数据实现和SAN相似的功能可以大大的降低成本,同时提高系统的灵活性。iSCSI就是这样一种技术,它利用普通的TCP/IP网来传输本来用存储区域网来传输的SCSI数据块。iSCSI的成本相对SAN来说要低不少。随着千兆网的普及,万兆网也逐渐的进入主流,使iSCSI的速度相对SAN来说并没有太大的劣势。iSCSI目前存在的主要问题是:(1)新兴的技术,提供完整解决方案的厂商较少,对管理者技术要求高;(2)通过普通网卡存取iSCSI数据时,解码成SCSI需要CPU进行运算,增加了系统性能开销,如果采用专门的 iSCSI网卡虽然可以减少系统性能开销,但会大大增加成本;(3)使用数据
网络进行存取,存取速度冗余受网络运行状况的影响。 
    

        通过以上分析,下表总结了这四种方式的主要区别。 
通过以上比较研究,四种方案各有优劣。对于小型且服务较为集中的商业
企业,可采用简单的DAS方案。对于中小型商业企业,服务器数量比较少,有一定的数据集中管理要求,且没有大型数据库需求的可采用NAS方案。对于大中型商业企业,SAN和iSCSI是较好的选择。如果希望使用存储的服务器相对比较集中,且对系统性能要求极高,可考虑采用SAN方案;对于希望使用存储的服务器相对比较分散,又对性能要求不是很高的,可以考虑采用iSCSI方案。

Continue reading 【转】几种常见的网络存储技术的比较研究

【转】回车键触发表单提交的问题


回车键触发表单提交的问题

我们有时候希望回车键敲在文本框(input element)里来提交表单(form),但有时候又不希望如此。比如搜索行为,希望输入完关键词之后直接按回车键立即提交表单,而有些复杂表单,可能要避免回车键误操作在未完成表单填写的时候就触发了表单提交。
要控制这些行为,不需要借助JS,浏览器已经帮我们做了这些处理,这里总结几条规则:
1、如果表单里有一个type=”submit”的按钮,回车键生效。
2、如果表单里只有一个type=”text”的input,不管按钮是什么type,回车键生效。
3、如果按钮不是用input,而是用button,并且没有加type,IE下默认为type=button,FF默认为type=submit。
4、其他表单元素如textarea、select不影响,radio checkbox不影响触发规则,但本身在FF下会响应回车键,在IE下不响应。
5、type=”image”的input,效果等同于type=”submit”,不知道为什么会设计这样一种type,不推荐使用,应该用CSS添加背景图合适些。
实际应用的时候,要让表单响应回车键很容易,保证表单里有个type=”submit”的按钮就行。而当只有一个文本框又不希望响应回车键怎么办呢?我的方法有点别扭,就是再写一个无意义的文本框,隐藏起来 但是如果设置了submit tabindex=0,则会提交  。根据第3条规则,我们在用button的时候,尽量显式声明type以使浏览器表现一致。

Continue reading 【转】回车键触发表单提交的问题

C/S与B/S架构

为了区别于传统的C/S模式,才特意将其称为B/S模式。认识到这些结构的特征,对于系统的选型而言是很关键的。 
1、系统的性能 
在系统的性能方面,B/S占有优势的是其异地浏览和信息采集的灵活性。任何时间、任何地点、任何系统,只要可以使用浏览器上网,就可以使用B/S系统的终端。 
不过,采用B/S结构,客户端只能完成浏览、查询、数据输入等简单功能,绝大部分工作由服务器承担,这使得服务器的负担很重。采用C/S结构时,客户端和服务器端都能够处理任务,这虽然对客户机的要求较高,但因此可以减轻服务器的压力。而且,由于客户端使用浏览器,使得网上发布的信息必须是以HTML格式为主,其它格式文件多半是以附件的形式存放。而HTML格式文件(也就是Web页面)不便于编辑修改,给文件管理带来了许多不便。 
2、系统的开发 
C/S 结构是建立在中间件产品基础之上的,要求应用开发者自己去处理事务管理、消息队列、数据的复制和同步、通信安全等系统级的问题。这对应用开发者提出了较高的要求,而且迫使应用开发者投入很多精力来解决应用程序以外的问题。这使得应用程序的维护、移植和互操作变得复杂。如果客户端是在不同的操作系统上,C/S结构的软件需要开发不同版本的客户端软件。但是,与B/S结构相比,C/S技术发展历史更为“悠久”。从技术成熟度及软件设计、开发人员的掌握水平来看,C/S技术应是更成熟、更可靠的。 
3、系统的升级维护 
C/S系统的各部分模块中有一部分改变,就要关联到其它模块的变动,使系统升级成本比较大。B/S与C/S处理模式相比,则大大简化了客户端,只要客户端机器能上网就可以。对于B/S而言,开发、维护等几乎所有工作也都集中在服务器端,当企业对网络应用进行升级时,只需更新服务器端的软件就可以,这减轻了异地用户系统维护与升级的成本。如果客户端的软件系统升级比较频繁,那么B/S架构的产品优势明显——所有的升级操作只需要针对服务器进行,这对那些点多面广的应用是很有价值的,例如一些招聘网站就需要采用B/S模式,客户端分散,且应用简单,只需要进行简单的浏览和少量信息的录入。 
4、C/S 模式的优点和缺点 
★ C/S 模式的优点 
● 由于客户端实现与服务器的直接相连,没有中间环节,因此响应速度快。 
操作界面漂亮、形式多样,可以充分满足客户自身的个性化要求。 
● C/S结构的管理信息系统具有较强的事务处理能力,能实现复杂的业务流程。
★ C/S 模式的缺点 
● 需要专门的客户端安装程序,分布功能弱,针对点多面广且不具备网络条件的用户群体,不能够实现快速部署安装和配置。 
兼容性差,对于不同的开发工具,具有较大的局限性。若采用不同工具,需要重新改写程序。 
开发成本较高,需要具有一定专业水准的技术人员才能完成。 
5、B/S模式的优点和缺点 
★ B/S 模式的优点 
具有分布性特点,可以随时随地进行查询、浏览等业务处理。 
● 业务扩展简单方便,通过增加网页即可增加服务器功能。 
● 维护简单方便,只需要改变网页,即可实现所有用户的同步更新。 
● 开发简单,共享性强。 
★ B/S 模式的缺点 
● 个性化特点明显降低,无法实现具有个性化的功能要求。 
● 操作是以鼠标为最基本的操作方式,无法满足快速操作的要求。 
● 页面动态刷新,响应速度明显降低。 
● 无法实现本地分页缓存显示,给数据库访问造成较大的压力。 
功能弱化,难以实现传统模式下的特殊功能要求。



c/s,b/s混用
异地查询,浏览等,功能简单,数据量小,安全要求低的可通过b/s实现。
对于数据量大,功能复杂,安全要求高的则使用c/s实现。

Continue reading C/S与B/S架构

JAVA内存泄漏——内存泄漏原因和内存泄漏检测工具

摘要 
虽然Java虚拟机(JVM)及其垃圾收集器(garbage collector,GC)负责管理大多数的内存任务,Java软件程序中还是有可能出现内存泄漏。实际上,这在大型项目中 是一个常见的问题。避免内存泄漏的第一步是要弄清楚它是如何发生的。本文介绍了编写Java代码的一些常见的内存泄漏陷阱,以及编写不泄漏代码的一些最佳 实践。一旦发生了内存泄漏,要指出造成泄漏的代码是非常困难的。因此本文还介绍了一种新工具,用来诊断泄漏并指出根本原因。该工具的开销非常小,因此可以 使用它来寻找处于生产中的系统的内存泄漏。

垃圾收集器的作用

虽然垃圾收集器处理了大多数内存管理问题,从而使编程人员的生活变得更轻松了,但是编程人员还是可能犯错而导致出现内存问题。简单地说,GC循 环地跟踪所有来自“根”对象(堆栈对象、静态对象、JNI句柄指向的对象,诸如此类)的引用,并将所有它所能到达的对象标记为活动的。程序只可以操纵这些 对象;其他的对象都被删除了。因为GC使程序不可能到达已被删除的对象,这么做就是安全的。

虽然内存管理可以说是自动化的,但是这并不能使编程人员免受思考内存管理问题之苦。例如,分配(以及释放)内存总会有开销,虽然这种开销对编程人员来说是不可见的。创建了太多对象的程序将会比完成同样的功能而创建的对象却比较少的程序更慢一些(在其他条件相同的情况下)。

而且,与本文更为密切相关的是,如果忘记“释放”先前分配的内存,就可能造成内存泄漏。 如果程序保留对永远不再使用的对象的引用,这些对象将会占用并耗尽内存,这是因为自动化的垃圾收集器无法证明这些对象将不再使用。正如我们先前所说的,如 果存在一个对对象的引用,对象就被定义为活动的,因此不能删除。为了确保能回收对象占用的内存,编程人员必须确保该对象不能到达。这通常是通过将对象字段 设置为null或者从集合(collection)中移除对象而完成的。但是,注意,当局部变量不再使用时,没有必要将其显式地设置为null。对这些变 量的引用将随着方法的退出而自动清除。

概括地说,这就是内存托管语言中的内存泄漏产生的主要原因:保留下来却永远不再使用的对象引用。

典型泄漏

既然我们知道了在Java中确实有可能发生内存泄漏,就让我们来看一些典型的内存泄漏及其原因。

全局集合

在大的应用程序中有某种全局的数据储存库是很常见的,例如一个JNDI树或一个会话表。在这些情况下,必须注意管理储存库的大小。必须有某种机制从储存库中移除不再需要的数据。

这可能有多种方法,但是最常见的一种是周期性运行的某种清除任务。该任务将验证储存库中的数据,并移除任何不再需要的数据。

另一种管理储存库的方法是使用反向链接(referrer)计数。然后集合负责统计集合中每个入口的反向链接的数目。这要求反向链接告诉集合何时会退出入口。当反向链接数目为零时,该元素就可以从集合中移除了。

缓存

缓存是一种数据结构,用于快速查找已经执行的操作的结果。因此,如果一个操作执行起来很慢,对于常用的输入数据,就可以将操作的结果缓存,并在下次调用该操作时使用缓存的数据。

缓存通常都是以动态方式实现的,其中新的结果是在执行时添加到缓存中的。典型的算法是:

检查结果是否在缓存中,如果在,就返回结果。 
如果结果不在缓存中,就进行计算。 
将计算出来的结果添加到缓存中,以便以后对该操作的调用可以使用。 
该算法的问题(或者说是潜在的内存泄漏)出在最后一步。如果调用该操作时有相当多的不同输入,就将有相当多的结果存储在缓存中。很明显这不是正确的方法。

为了预防这种具有潜在破坏性的设计,程序必须确保对于缓存所使用的内存容量有一个上限。因此,更好的算法是:

检查结果是否在缓存中,如果在,就返回结果。 
如果结果不在缓存中,就进行计算。 
如果缓存所占的空间过大,就移除缓存最久的结果。 
将计算出来的结果添加到缓存中,以便以后对该操作的调用可以使用。 
通过始终移除缓存最久的结果,我们实际上进行了这样的假设:在将来,比起缓存最久的数据,最近输入的数据更有可能用到。这通常是一个不错的假设。

新算法将确保缓存的容量处于预定义的内存范围之内。确切的范围可能很难计算,因为缓存中的对象在不断变化,而且它们的引用包罗万象。为缓存设置正确的大小是一项非常复杂的任务,需要将所使用的内存容量与检索数据的速度加以平衡。

解决这个问题的另一种方法是使用java.lang.ref.SoftReference类跟踪缓存中的对象。这种方法保证这些引用能够被移除,如果虚拟机的内存用尽而需要更多堆的话。

ClassLoader

Java ClassLoader结构的使用为内存泄漏提供了许多可乘之机。正是该结构本身的复杂性使ClassLoader在内存泄漏方面存在如此多的问题。 ClassLoader的特别之处在于它不仅涉及“常规”的对象引用,还涉及元对象引用,比如:字段、方法和类。这意味着只要有对字段、方法、类或 ClassLoader的对象的引用,ClassLoader就会驻留在JVM中。因为ClassLoader本身可以关联许多类及其静态字段,所以就有 许多内存被泄漏了。

确定泄漏的位置

通常发生内存泄漏的第一个迹象是:在应用程序中出现了OutOfMemoryError。这通常发生在您最不愿意它发生的生产环境中,此时几乎 不能进行调试。有可能是因为测试环境运行应用程序的方式与生产系统不完全相同,因而导致泄漏只出现在生产中。在这种情况下,需要使用一些开销较低的工具来 监控和查找内存泄漏。还需要能够无需重启系统或修改代码就可以将这些工具连接到正在运行的系统上。可能最重要的是,当进行分析时,需要能够断开工具而保持 系统不受干扰。

虽然OutOfMemoryError通常都是内存泄漏的信号,但是也有可能应用程序确实正在使用这么多的内存;对于后者,或者必须增加JVM 可用的堆的数量,或者对应用程序进行某种更改,使它使用较少的内存。但是,在许多情况下,OutOfMemoryError都是内存泄漏的信号。一种查明 方法是不间断地监控GC的活动,确定内存使用量是否随着时间增加。如果确实如此,就可能发生了内存泄漏。

详细输出

有许多监控垃圾收集器活动的方法。而其中使用最广泛的可能是使用-Xverbose:gc选项启动JVM,并观察输出。

[memory ] 10.109-10.235: GC 65536K->16788K (65536K), 126.000 ms 
箭头后面的值(本例中是16788K)是垃圾收集所使用的堆的容量。

控制台

查看连续不断的GC的详细统计信息的输出将是非常乏味的。幸好有这方面的工具。JRockit Management Console可以显示堆使用量的图示。借助于该图,可以很容易地看出堆使用量是否随时间增加。
diyblPic 
Figure 1. The JRockit Management Console

甚至可以配置该管理控制台,以便如果发生堆使用量过大的情况(或基于其他的事件),控制台能够向您发送电子邮件。这明显使内存泄漏的查看变得更容易了。

内存泄漏检测工具

还有其他的专门进行内存泄漏检测的工具。JRockit Memory Leak Detector可以用来查看内存泄漏,并可以更深入地查出泄漏的根源。这个强大的工具是紧密集成到JRockit JVM中的,其开销非常小,对虚拟机的堆的访问也很容易。

专业工具的优点

一旦知道确实发生了内存泄漏,就需要更专业的工具来查明为什么会发生泄漏。JVM自己是不会告诉您的。这些专业 工具从JVM获得内存系统信息的方法基本上有两种:JVMTI和字节码技术(byte code instrumentation)。Java虚拟机工具接口(Java Virtual Machine Tools Interface,JVMTI)及其前身Java虚拟机监视程序接口(Java Virtual Machine Profiling Interface,JVMPI)是外部工具与JVM通信并从JVM收集信息的标准化接口。字节码技术是指使用探测器处理字节码以获得工具所需的信息的技 术。

对于内存泄漏检测来说,这两种技术有两个缺点,这使它们不太适合用于生产环境。首先,它们在内存占用和性能降低 方面的开销不可忽略。有关堆使用量的信息必须以某种方式从JVM导出,并收集到工具中进行处理。这意味着要为工具分配内存。信息的导出也影响了JVM的性 能。例如,当收集信息时,垃圾收集器将运行得比较慢。另外一个缺点是需要始终将工具连在JVM上。这是不可能的:将工具连在一个已经启动的JVM上,进行 分析,断开工具,并保持JVM运行。

因为JRockit Memory Leak Detector是集成到JVM中的,就没有这两个缺点了。首先,许多处理和分析工作是 在JVM内部进行的,所以没有必要转换或重新创建任何数据。处理还可以背负(piggyback)在垃圾收集器本身上而进行,这意味着提高了速度。其次, 只要JVM是使用-Xmanagement选项(允许通过远程JMX接口监控和管理JVM)启动的,Memory Leak Detector就可以与运行中的JVM进行连接或断开。当该工具断开时,没有任何东西遗留在JVM中,JVM又将以全速运行代码,正如工具连接之前一 样。

趋势分析

让我们深入地研究一下该工具以及它是如何用来跟踪内存泄漏的。在知道发生内存泄漏之后,第一步是要弄清楚泄漏了 什么数据--哪个类的对象引起了泄漏?JRockit Memory Leak Detector是通过在每次垃圾收集时计算每个类的现有对象的数目来实现这一步的。如果特定类的对象数目随时间而增长(“增长率”),就可能发生了内存 泄漏。

diyblPic 
图2. Memory Leak Detector的趋势分析视图

因为泄漏可能像细流一样非常小,所以趋势分析必须运行很长一段时间。在短时间内,可能会发生一些类的局部增长, 而之后它们又会跌落。但是趋势分析的开销很小(最大开销也不过是在每次垃圾收集时将数据包由JRockit发送到Memory Leak Detector)。开销不应该成为任何系统的问题——即使是一个全速运行的生产中的系统。

起初数目会跳跃不停,但是一段时间之后它们就会稳定下来,并显示出哪些类的数目在增长。

找出根本原因

有时候知道是哪些类的对象在泄漏就足以说明问题了。这些类可能只用于代码中的非常有限的部分,对代码进行一次快 速检查就可以显示出问题所在。遗憾地是,很有可能只有这类信息还并不够。例如,常见到泄漏出在类java.lang.String的对象上,但是因为字符 串在整个程序中都使用,所以这并没有多大帮助。

我们想知道的是,另外还有哪些对象与泄漏对象关联?在本例中是String。为什么泄漏的对象还存在?哪些对象 保留了对这些对象的引用?但是能列出的所有保留对String的引用的对象将会非常多,以至于没有什么实际用处。为了限制数据的数量,可以将数据按类分 组,以便可以看出其他哪些对象的类与泄漏对象(String)关联。例如,String在Hashtable中是很常见的,因此我们可能会看到与 String关联的Hashtable数据项对象。由Hashtable数据项倒推,我们最终可以找到与这些数据项有关的Hashtable对象以及 String(如图3所示)。

diyblPic 
图3. 在工具中看到的类型图的示例视图

倒推

因为我们仍然是以类的对象而不是单独的对象来看待对象,所以我们不知道是哪个Hashtable在泄漏。如果我 们可以弄清楚系统中所有的Hashtable都有多大,我们就可以假定最大的Hashtable就是正在泄漏的那一个(因为随着时间的流逝它会累积泄漏而 增长得相当大)。因此,一份有关所有Hashtable对象以及它们引用了多少数据的列表,将会帮助我们指出造成泄漏的确切Hashtabl。

diyblPic 
图4. 界面:Hashtable对象以及它们所引用数据的数量的列表

对对象引用数据数目的计算开销非常大(需要以该对象作为根遍历引用图),如果必须对许多对象都这么做,将会花很 多时间。如果了解一点Hashtable的内部实现原理就可以找到一条捷径。Hashtable的内部有一个Hashtable数据项的数组。该数组随着 Hashtable中对象数目的增长而增长。因此,为找出最大的Hashtable,我们只需找出引用Hashtable数据项的最大数组。这样要快很 多。

diyblPic 
图5. 界面:最大的Hashtable数据项数组及其大小的清单

更进一步

当找到发生泄漏的Hashtable实例时,我们可以看到其他哪些实例在引用该Hashtable,并倒推回去看看是哪个Hashtable在泄漏。

diyblPic 
图 6. 这就是工具中的实例图

例如,该Hashtable可能是由MyServer类型的对象在名为activeSessions的字段中引用的。这种信息通常就足以查找源代码以定位问题所在了。

diyblPic 
图7. 检查对象以及它对其他对象的引用

找出分配位置

当跟踪内存泄漏问题时,查看对象分配到哪里是很有用的。只知道它们如何与其他对象相关联(即哪些对象引用了它 们)是不够的,关于它们在何处创建的信息也很有用。当然了,您并不想创建应用程序的辅助构件,以打印每次分配的堆栈跟踪(stack trace)。您也不想仅仅为了跟踪内存泄漏而在运行应用程序时将一个分析程序连接到生产环境中。

借助于JRockit Memory Leak Detector,应用程序中的代码可以在分配时进行动态添加,以创建堆栈跟踪。这些堆栈跟踪可以在工具中进行累积和分析。只要不启用就不会因该功能而产 生成本,这意味着随时可以进行分配跟踪。当请求分配跟踪时,JRockit 编译器动态插入代码以监控分配,但是只针对所请求的特定类。更好的是,在进行数据分析时,添加的代码全部被移除,代码中没有留下任何会引起应用程序性能降 低的更改。

diyblPic 
图8. 示例程序执行期间String的分配的堆栈跟踪

结束语

内存泄漏是难以发现的。本文重点介绍了几种避免内存泄漏的最佳实践,包括要始终记住在数据结构中所放置的内容,以及密切监控内存使用量以发现突然的增长。

我们都已经看到了JRockit Memory Leak Detector是如何用于生产中的系统以跟踪内存泄漏的。该工具使用一种三步式的方法来找出泄漏。首先,进行趋势分析,找出是哪个类的对象在泄漏。接下 来,看看有哪些其他的类与泄漏的类的对象相关联。最后,进一步研究单个对象,看看它们是如何互相关联的。也有可能对系统中所有对象分配进行动态的堆栈跟 踪。这些功能以及该工具紧密集成到JVM中的特性使您可以以一种安全而强大的方式跟踪内存泄漏并进行修复

我在这里举个例子:

java.lang.OutOfMemoryError这个错都见过,这就是内存泄露的结果。

在effective java item6中 讲了如下的例子:

public class Stack {
private Object[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
public Stack() {
elements = new Object[DEFAULT_INITIAL_CAPACITY];
}
public void push(Object e) {
ensureCapacity();
elements[size++] = e;
}
public Object pop() {
if (size == 0)
throw new EmptyStackException();
return elements[—size]; //这里仍存在对pop出去对象的强引用,问题来了
}
/**
* Ensure space for at least one more element, roughly
* doubling the capacity each time the array needs to grow.
*/
private void ensureCapacity() {
if (elements.length == size)
elements = Arrays.copyOf(elements, 2 * size + 1);
}
}

应该修改如下:

public Object pop() {
if (size == 0)
throw new EmptyStackException();
Object result = elements[--size];
elements[size] = null; // Eliminate obsolete reference
return result;
}

内存泄露(Memory Leak)还有个名称叫做

unintentional object retentions 非故意对象闭留

Continue reading JAVA内存泄漏——内存泄漏原因和内存泄漏检测工具

在ie下,button 标记恐怕还存在几个不大不小的问题。

在ie下,<button>标记恐怕还存在几个不大不小的问题。

  1. 在一个表单里,如果有一个以上"submit"类型的<button>标签存在,在表单被提交时,不管你点击哪个<button>,所有<button>的值都会被post/get。
  2. <button>的缺省type属性被设置为"button",但是在A级别浏览器下,应该设置为"submit"才对
  3. 如果你用javascript去访问<button>的value属性,IE却返回了<button>的innerHTML属性,很让人恼火。 (可以使用"getAttributeNode"方法来避免.)

例如,一段HTML:

CODE:
  1. <form>
  2. <button type="submit" value="1" name="action-1">text 1</button>
  3. <button type="submit" value="2" name="action-2">text 2</button>
  4. </form>

在IE下,上面两个button的数据都会被提交。并且ie会提交这两个button的innerText而不是value。而其它浏览器仅仅提交你点击的那个button。

Continue reading 在ie下,button 标记恐怕还存在几个不大不小的问题。

Pagination


Total views.

© 2013 - 2019. All rights reserved.

Powered by Hydejack v6.6.1