﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-道非道  非常道-文章分类-JAVA SE</title><link>http://www.blogjava.net/gen-sky/category/40682.html</link><description>勤思、谨言、慎行、厚积、薄发</description><language>zh-cn</language><lastBuildDate>Thu, 28 Feb 2013 16:38:01 GMT</lastBuildDate><pubDate>Thu, 28 Feb 2013 16:38:01 GMT</pubDate><ttl>60</ttl><item><title>spring3  email  发送代码 </title><link>http://www.blogjava.net/gen-sky/articles/spring3_email.html</link><dc:creator>星期五</dc:creator><author>星期五</author><pubDate>Thu, 28 Feb 2013 10:08:00 GMT</pubDate><guid>http://www.blogjava.net/gen-sky/articles/spring3_email.html</guid><wfw:comment>http://www.blogjava.net/gen-sky/comments/395869.html</wfw:comment><comments>http://www.blogjava.net/gen-sky/articles/spring3_email.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gen-sky/comments/commentRss/395869.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gen-sky/services/trackbacks/395869.html</trackback:ping><description><![CDATA[使用spring3来进行java 邮件的发送。闲话不说，直接上代码。<br />配置代码都超过了主代码&nbsp;<br />不过配置代码都是常用的，留着备份吧。<br />mavne pox 配置<br /><br /><br /><br /><div style="padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; width: 1154.4375px; word-break: break-all;"><span style="color: #008080;">&nbsp;1</span>&nbsp;<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">dependency</span><span style="color: #0000ff;">&gt;</span><br /><span style="color: #008080;">&nbsp;2</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">groupId</span><span style="color: #0000ff;">&gt;</span>javax.mail<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">groupId</span><span style="color: #0000ff;">&gt;</span><br /><span style="color: #008080;">&nbsp;3</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">artifactId</span><span style="color: #0000ff;">&gt;</span>mail<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">artifactId</span><span style="color: #0000ff;">&gt;</span><br /><span style="color: #008080;">&nbsp;4</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">version</span><span style="color: #0000ff;">&gt;</span>1.4<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">version</span><span style="color: #0000ff;">&gt;</span><br /><span style="color: #008080;">&nbsp;5</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">dependency</span><span style="color: #0000ff;">&gt;</span><br /><span style="color: #008080;">&nbsp;6</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">dependency</span><span style="color: #0000ff;">&gt;</span><br /><span style="color: #008080;">&nbsp;7</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">groupId</span><span style="color: #0000ff;">&gt;</span>org.springframework<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">groupId</span><span style="color: #0000ff;">&gt;</span><br /><span style="color: #008080;">&nbsp;8</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">artifactId</span><span style="color: #0000ff;">&gt;</span>spring-beans<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">artifactId</span><span style="color: #0000ff;">&gt;</span><br /><span style="color: #008080;">&nbsp;9</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">version</span><span style="color: #0000ff;">&gt;</span>${org.springframework.version}<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">version</span><span style="color: #0000ff;">&gt;</span><br /><span style="color: #008080;">10</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">dependency</span><span style="color: #0000ff;">&gt;</span></div><br />spring-xml 配置<br /><div style="padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; width: 1154.4375px; word-break: break-all;"><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">bean&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="propertyConfigurer"</span><span style="color: #ff0000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class</span><span style="color: #0000ff;">="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"</span><span style="color: #0000ff;">&gt;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">property&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="locations"</span><span style="color: #0000ff;">&gt;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">list</span><span style="color: #0000ff;">&gt;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">value</span><span style="color: #0000ff;">&gt;</span>classpath:cfg/config.properties<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">value</span><span style="color: #0000ff;">&gt;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">list</span><span style="color: #0000ff;">&gt;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">property</span><span style="color: #0000ff;">&gt;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">bean</span><span style="color: #0000ff;">&gt;</span><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">bean&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="mail"</span><span style="color: #ff0000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class</span><span style="color: #0000ff;">="org.springframework.mail.javamail.JavaMailSenderImpl"</span><span style="color: #0000ff;">&gt;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000;">&lt;!--</span><span style="color: #008000;">&nbsp;SMTP发送邮件的服务器的IP和端口&nbsp;</span><span style="color: #008000;">--&gt;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">property&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="host"</span><span style="color: #ff0000;">&nbsp;value</span><span style="color: #0000ff;">="${mail.host}"</span>&nbsp;<span style="color: #0000ff;">/&gt;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">property&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="port"</span><span style="color: #ff0000;">&nbsp;value</span><span style="color: #0000ff;">="${mail.port}"</span>&nbsp;<span style="color: #0000ff;">/&gt;</span><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000;">&lt;!--</span><span style="color: #008000;">&nbsp;登陆SMTP邮件发送服务器的用户名和密码&nbsp;</span><span style="color: #008000;">--&gt;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">property&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="username"</span><span style="color: #ff0000;">&nbsp;value</span><span style="color: #0000ff;">="${mail.username}"</span>&nbsp;<span style="color: #0000ff;">/&gt;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">property&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="password"</span><span style="color: #ff0000;">&nbsp;value</span><span style="color: #0000ff;">="${mail.password}"</span>&nbsp;<span style="color: #0000ff;">/&gt;</span><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000;">&lt;!--</span><span style="color: #008000;">&nbsp;获得邮件会话属性,验证登录邮件服务器是否成功</span><span style="color: #008000;">--&gt;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">property&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="javaMailProperties"</span><span style="color: #0000ff;">&gt;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">props</span><span style="color: #0000ff;">&gt;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">prop&nbsp;</span><span style="color: #ff0000;">key</span><span style="color: #0000ff;">="mail.smtp.auth"</span><span style="color: #0000ff;">&gt;</span>true<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">prop</span><span style="color: #0000ff;">&gt;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">prop&nbsp;</span><span style="color: #ff0000;">key</span><span style="color: #0000ff;">="prop"</span><span style="color: #0000ff;">&gt;</span>true<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">prop</span><span style="color: #0000ff;">&gt;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">prop&nbsp;</span><span style="color: #ff0000;">key</span><span style="color: #0000ff;">="mail.smtp.timeout"</span><span style="color: #0000ff;">&gt;</span>25000<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">prop</span><span style="color: #0000ff;">&gt;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">props</span><span style="color: #0000ff;">&gt;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">property</span><span style="color: #0000ff;">&gt;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">bean</span><span style="color: #0000ff;">&gt;</span></div><br /><br />properties 文件配置<br /><br /><div style="padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; width: 1154.4375px; word-break: break-all;">mail.host=smtp.yeah.net<br />mail.port=25<br />mail.username=****<br />mail.password=****</div>java 类分别为：<br /><br /><div style="padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; width: 1154.4375px; word-break: break-all;"><span style="color: #0000ff;">import</span>&nbsp;org.springframework.context.support.AbstractApplicationContext;<br /><br /><span style="color: #0000ff;">import</span>&nbsp;com.ms.AppContext;<br /><br /><span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">class</span>&nbsp;SpringHelper&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000;">/**</span><span style="color: #008000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;获取spring依赖注入的对象<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;name<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@return</span><span style="color: #008000;">&nbsp;Object&nbsp;Bean<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">static</span>&nbsp;Object&nbsp;getBean(String&nbsp;name)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AbstractApplicationContext&nbsp;ctx&nbsp;=&nbsp;AppContext.getInstance()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.getAppContext();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">return</span>&nbsp;ctx.getBean(name);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}</div><br /><br /><div style="padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; width: 1154.4375px; word-break: break-all;"><span style="color: #0000ff;">import</span>&nbsp;java.util.ArrayList;<br /><span style="color: #0000ff;">import</span>&nbsp;java.util.List;<br /><br /><span style="color: #0000ff;">import</span>&nbsp;org.springframework.context.support.AbstractApplicationContext;<br /><span style="color: #0000ff;">import</span>&nbsp;org.springframework.context.support.ClassPathXmlApplicationContext;<br /><br /><span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">class</span>&nbsp;AppContext&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">private</span>&nbsp;<span style="color: #0000ff;">static</span>&nbsp;AppContext&nbsp;instance;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">private</span>&nbsp;<span style="color: #0000ff;">volatile</span>&nbsp;AbstractApplicationContext&nbsp;appContext;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">synchronized</span>&nbsp;<span style="color: #0000ff;">static</span>&nbsp;AppContext&nbsp;getInstance()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">if</span>&nbsp;(instance&nbsp;==&nbsp;<span style="color: #0000ff;">null</span>)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;instance&nbsp;=&nbsp;<span style="color: #0000ff;">new</span>&nbsp;AppContext();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">return</span>&nbsp;instance;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">private</span>&nbsp;AppContext()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&lt;String&gt;&nbsp;list&nbsp;=&nbsp;<span style="color: #0000ff;">new</span>&nbsp;ArrayList&lt;String&gt;();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.add("/cfg/*.xml");<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;ss[]&nbsp;=&nbsp;list.toArray(<span style="color: #0000ff;">new</span>&nbsp;String[]&nbsp;{});<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">for</span>&nbsp;(<span style="color: #0000ff;">int</span>&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;ss.length;&nbsp;i++)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("ss["&nbsp;+&nbsp;i&nbsp;+&nbsp;"]"&nbsp;+&nbsp;ss[i]);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">this</span>.appContext&nbsp;=&nbsp;<span style="color: #0000ff;">new</span>&nbsp;ClassPathXmlApplicationContext(ss);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">public</span>&nbsp;AbstractApplicationContext&nbsp;getAppContext()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">return</span>&nbsp;appContext;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}</div><br /><br /><div style="padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; width: 1154.4375px; word-break: break-all;"><br /><span style="color: #0000ff;">import</span>&nbsp;java.io.File;<br /><span style="color: #0000ff;">import</span>&nbsp;java.util.Date;<br /><br /><span style="color: #0000ff;">import</span>&nbsp;javax.mail.internet.InternetAddress;<br /><span style="color: #0000ff;">import</span>&nbsp;javax.mail.internet.MimeMessage;<br /><span style="color: #0000ff;">import</span>&nbsp;javax.mail.internet.MimeUtility;<br /><br /><span style="color: #0000ff;">import</span>&nbsp;org.apache.log4j.Logger;<br /><span style="color: #0000ff;">import</span>&nbsp;org.apache.log4j.PropertyConfigurator;<br /><span style="color: #0000ff;">import</span>&nbsp;org.springframework.mail.SimpleMailMessage;<br /><span style="color: #0000ff;">import</span>&nbsp;org.springframework.mail.javamail.JavaMailSender;<br /><span style="color: #0000ff;">import</span>&nbsp;org.springframework.mail.javamail.MimeMessageHelper;<br /><br /><span style="color: #0000ff;">import</span>&nbsp;com.ms.SpringHelper;<br /><span style="color: #0000ff;">import</span>&nbsp;com.util.Configuration;<br /><br /><span style="color: #008000;">/**</span><span style="color: #008000;"><br />&nbsp;*&nbsp;发送邮件&nbsp;工具<br />&nbsp;*&nbsp;<br />&nbsp;*&nbsp;</span><span style="color: #808080;">@author</span><span style="color: #008000;">&nbsp;<br />&nbsp;*&nbsp;@file&nbsp;com.ms.util&nbsp;---&nbsp;SentMaileUtil.java<br />&nbsp;*&nbsp;</span><span style="color: #808080;">@version</span><span style="color: #008000;">&nbsp;2013-2-28&nbsp;-下午03:42:03<br />&nbsp;</span><span style="color: #008000;">*/</span><br /><span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">class</span>&nbsp;SendMaileUtil&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">private</span>&nbsp;<span style="color: #0000ff;">static</span>&nbsp;JavaMailSender&nbsp;javaMailSender;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">private</span>&nbsp;<span style="color: #0000ff;">static</span>&nbsp;Logger&nbsp;logger&nbsp;=&nbsp;Logger.getLogger(SendMaileUtil.<span style="color: #0000ff;">class</span>);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">private</span>&nbsp;<span style="color: #0000ff;">static</span>&nbsp;JavaMailSender&nbsp;newIntstance()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">if</span>&nbsp;(javaMailSender&nbsp;==&nbsp;<span style="color: #0000ff;">null</span>)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;javaMailSender&nbsp;=&nbsp;(JavaMailSender)&nbsp;SpringHelper.getBean("mail");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">return</span>&nbsp;javaMailSender;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000;">/**</span><span style="color: #008000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;发送的文本测试邮件<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;to<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;mailSubject<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;mailBody<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">static</span>&nbsp;<span style="color: #0000ff;">void</span>&nbsp;sendTextMaile(String&nbsp;to,&nbsp;String&nbsp;mailSubject,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;mailBody)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">if</span>&nbsp;(logger.isDebugEnabled())<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.debug("准备发送文本形式的邮件<img src="http://www.blogjava.net/Images/dot.gif" alt="" />");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SimpleMailMessage&nbsp;mail1&nbsp;=&nbsp;<span style="color: #0000ff;">new</span>&nbsp;SimpleMailMessage();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;from&nbsp;=&nbsp;Configuration.getValue("mail.form");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mail1.setFrom(from);<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;发送人名片</span><span style="color: #008000;"><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mail1.setTo(to);<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;收件人邮箱</span><span style="color: #008000;"><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mail1.setSubject(mailSubject);<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;邮件主题</span><span style="color: #008000;"><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mail1.setSentDate(<span style="color: #0000ff;">new</span>&nbsp;Date());<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;邮件发送时间</span><span style="color: #008000;"><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mail1.setText(mailBody);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;群发</span><span style="color: #008000;"><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SimpleMailMessage[]&nbsp;mailMessages&nbsp;=&nbsp;{&nbsp;mail1&nbsp;};<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newIntstance().send(mailMessages);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">if</span>&nbsp;(logger.isDebugEnabled())<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.debug("文本形式的邮件发送成功！！！");<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000;">/**</span><span style="color: #008000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;以&nbsp;HTML脚本形式邮件发送<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;to<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;mailSubject<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;mailBody<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">static</span>&nbsp;<span style="color: #0000ff;">void</span>&nbsp;sendHtmlMail(String&nbsp;to,&nbsp;String&nbsp;mailSubject,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;mailBody)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JavaMailSender&nbsp;mailSender&nbsp;=&nbsp;newIntstance();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MimeMessage&nbsp;mimeMessage&nbsp;=&nbsp;mailSender.createMimeMessage();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">try</span>&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">if</span>&nbsp;(logger.isDebugEnabled())<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.debug("HTML脚本形式邮件正在发送<img src="http://www.blogjava.net/Images/dot.gif" alt="" />");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;设置utf-8或GBK编码，否则邮件会有乱码</span><span style="color: #008000;"><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MimeMessageHelper&nbsp;helper&nbsp;=&nbsp;<span style="color: #0000ff;">new</span>&nbsp;MimeMessageHelper(mimeMessage,&nbsp;<span style="color: #0000ff;">true</span>,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"UTF-8");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;设置发送人名片</span><span style="color: #008000;"><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;from&nbsp;=&nbsp;Configuration.getValue("mail.form");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;helper.setFrom(from);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;设置收件人名片和地址</span><span style="color: #008000;"><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;helper.setTo(<span style="color: #0000ff;">new</span>&nbsp;InternetAddress("\""<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+&nbsp;MimeUtility.encodeText("gamil邮箱")&nbsp;+&nbsp;"\"&nbsp;&lt;"&nbsp;+&nbsp;to&nbsp;+&nbsp;"&gt;"));//&nbsp;发送者<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;邮件发送时间</span><span style="color: #008000;"><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;helper.setSentDate(<span style="color: #0000ff;">new</span>&nbsp;Date());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;设置回复地址</span><span style="color: #008000;"><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;helper.setReplyTo(<span style="color: #0000ff;">new</span>&nbsp;InternetAddress(from));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;设置抄送的名片和地址<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;helper.setCc(InternetAddress.parse(MimeUtility.encodeText("抄送人001")<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;+&nbsp;"&nbsp;&lt;<img src="http://www.blogjava.net/Images/dot.gif" alt="" />@163.com&gt;,"&nbsp;+&nbsp;MimeUtility.encodeText("抄送人002")<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;+&nbsp;"&nbsp;&lt;<img src="http://www.blogjava.net/Images/dot.gif" alt="" />@foxmail.com&gt;"));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;主题</span><span style="color: #008000;"><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;helper.setSubject("챔피언쉽");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;邮件内容，注意加参数true，表示启用html格式</span><span style="color: #008000;"><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;helper<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.setText(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"&lt;html&gt;&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;h1&gt;hello!!我是乔布斯&lt;/h1&gt;&lt;/body&gt;&lt;/html&gt;",<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">true</span>);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;发送</span><span style="color: #008000;"><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mailSender.send(mimeMessage);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000ff;">catch</span>&nbsp;(Exception&nbsp;e)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">if</span>&nbsp;(logger.isDebugEnabled())<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.debug("HTML脚本形式邮件发送成功！！！");<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000;">/**</span><span style="color: #008000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;以附件的形式发送邮件<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;to<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;收件人eamil&nbsp;地址<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;toName<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;收件人昵称<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;mailSubject<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;主题<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;mailBody<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;内容体<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;files<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;附件<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">static</span>&nbsp;<span style="color: #0000ff;">void</span>&nbsp;sendFileMail(String&nbsp;to,&nbsp;String&nbsp;toName,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;mailSubject,&nbsp;String&nbsp;mailBody,&nbsp;File[]&nbsp;files)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JavaMailSender&nbsp;mailSender&nbsp;=&nbsp;newIntstance();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MimeMessage&nbsp;mimeMessage&nbsp;=&nbsp;mailSender.createMimeMessage();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">try</span>&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">if</span>&nbsp;(logger.isDebugEnabled())<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.debug("带附件和图片的邮件正在发送<img src="http://www.blogjava.net/Images/dot.gif" alt="" />");<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;设置utf-8或GBK编码，否则邮件会有乱码</span><span style="color: #008000;"><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MimeMessageHelper&nbsp;helper&nbsp;=&nbsp;<span style="color: #0000ff;">new</span>&nbsp;MimeMessageHelper(mimeMessage,&nbsp;<span style="color: #0000ff;">true</span>,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"UTF-8");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;设置发送人名片</span><span style="color: #008000;"><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;from&nbsp;=&nbsp;Configuration.getValue("mail.form");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;helper.setFrom(from);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;设置收件人邮箱</span><span style="color: #008000;"><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;helper.setTo(<span style="color: #0000ff;">new</span>&nbsp;InternetAddress("\""<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+&nbsp;MimeUtility.encodeText(toName)&nbsp;+&nbsp;"\"&nbsp;&lt;"&nbsp;+&nbsp;to&nbsp;+&nbsp;"&gt;"));<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;设置回复地址<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;helper.setReplyTo(new&nbsp;InternetAddress("<img src="http://www.blogjava.net/Images/dot.gif" alt="" />@qq.com"));<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;设置收件人抄送的名片和地址(相当于群发了)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;helper.setCc(InternetAddress.parse(MimeUtility.encodeText("邮箱001")<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;+&nbsp;"&nbsp;&lt;<img src="http://www.blogjava.net/Images/dot.gif" alt="" />@163.com&gt;,"&nbsp;+&nbsp;MimeUtility.encodeText("邮箱002")<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;+&nbsp;"&nbsp;&lt;<img src="http://www.blogjava.net/Images/dot.gif" alt="" />@foxmail.com&gt;"));<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;主题</span><span style="color: #008000;"><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;helper.setSubject(mailSubject);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;邮件内容，注意加参数true，表示启用html格式</span><span style="color: #008000;"><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;helper.setText(mailBody);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">if</span>&nbsp;(files&nbsp;!=&nbsp;<span style="color: #0000ff;">null</span>&nbsp;&amp;&amp;&nbsp;files.length&nbsp;&gt;&nbsp;0)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">for</span>&nbsp;(<span style="color: #0000ff;">int</span>&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;files.length;&nbsp;i++)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;加入附件</span><span style="color: #008000;"><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;helper.addAttachment(MimeUtility.encodeText(files[i]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.getName()),&nbsp;files[i]);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;加入插图</span><span style="color: #008000;"><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;helper.addInline(MimeUtility.encodeText("pic01"),&nbsp;<span style="color: #0000ff;">new</span>&nbsp;File(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"c:/temp/2dd24be463.jpg"));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;发送</span><span style="color: #008000;"><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mailSender.send(mimeMessage);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000ff;">catch</span>&nbsp;(Exception&nbsp;e)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">if</span>&nbsp;(logger.isDebugEnabled())&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.debug("带附件和图片的邮件发送成功！！！");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">static</span>&nbsp;<span style="color: #0000ff;">void</span>&nbsp;main(String[]&nbsp;args)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PropertyConfigurator.configure(ClassLoader<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.getSystemResource("cfg/log4j.properties"));<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SendMaileUtil.sendTextMaile("*****@gmail.com",<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Spring&nbsp;Mail&nbsp;测试邮件",&nbsp;"Hello,Boy,This&nbsp;is&nbsp;my&nbsp;Spring&nbsp;Mail,哈哈！！");<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SendMaileUtil.sendHtmlMail("*****@gmail.com",&nbsp;<span style="color: #0000ff;">null</span>,&nbsp;<span style="color: #0000ff;">null</span>);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File&nbsp;file&nbsp;=&nbsp;<span style="color: #0000ff;">new</span>&nbsp;File("c:/temp");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File[]&nbsp;fs&nbsp;=&nbsp;file.listFiles();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SendMaileUtil.sendFileMail("******@yeah.net",&nbsp;"昵称",&nbsp;"主题",&nbsp;"内容",<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fs);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}</div><br /><br /><br /><br /><br /><br /><br /><br /><div style="padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; width: 1154.4375px; word-break: break-all;"><br /><span style="color: #0000ff;">import</span>&nbsp;java.io.FileInputStream;<br /><span style="color: #0000ff;">import</span>&nbsp;java.io.FileNotFoundException;<br /><span style="color: #0000ff;">import</span>&nbsp;java.io.IOException;<br /><span style="color: #0000ff;">import</span>&nbsp;java.io.InputStream;<br /><span style="color: #0000ff;">import</span>&nbsp;java.util.Properties;<br /><br /><span style="color: #0000ff;">import</span>&nbsp;com.pub.Forward;<br /><br /><span style="color: #008000;">/**</span><span style="color: #008000;"><br />&nbsp;*&nbsp;读取properties文件<br />&nbsp;*&nbsp;</span><span style="color: #808080;">@author</span><span style="color: #008000;">&nbsp;<br />&nbsp;*<br />&nbsp;</span><span style="color: #008000;">*/</span><br /><span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">class</span>&nbsp;Configuration<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">private</span>&nbsp;<span style="color: #0000ff;">static</span>&nbsp;Properties&nbsp;propertie;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">private</span>&nbsp;InputStream&nbsp;in;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">private</span>&nbsp;<span style="color: #0000ff;">static</span>&nbsp;Configuration&nbsp;config&nbsp;=&nbsp;<span style="color: #0000ff;">new</span>&nbsp;Configuration();<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000;">/**</span><span style="color: #008000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;初始化Configuration类<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">public</span>&nbsp;Configuration()<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;propertie&nbsp;=&nbsp;<span style="color: #0000ff;">new</span>&nbsp;Properties();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">try</span>&nbsp;{<br /><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(System.getProperty("user.dir"));<br /></span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inputFile&nbsp;=&nbsp;new&nbsp;FileInputStream("cfg/config.properties");</span><span style="color: #008000;"><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;in&nbsp;=&nbsp;&nbsp;ClassLoader.getSystemResourceAsStream("cfg/config.properties");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;propertie.load(in);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;in.close();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000ff;">catch</span>&nbsp;(FileNotFoundException&nbsp;ex)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("读取属性文件---&gt;失败！-&nbsp;原因：文件路径错误或者文件不存在");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ex.printStackTrace();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000ff;">catch</span>&nbsp;(IOException&nbsp;ex)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("装载文件---&gt;失败!");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ex.printStackTrace();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000;">/**</span><span style="color: #008000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;重载函数，得到key的值<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;key&nbsp;取得其值的键<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@return</span><span style="color: #008000;">&nbsp;key的值<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">static</span>&nbsp;&nbsp;String&nbsp;getValue(String&nbsp;key)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">if</span>(propertie.containsKey(key)){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;value&nbsp;=&nbsp;propertie.getProperty(key);<span style="color: #008000;">//</span><span style="color: #008000;">得到某一属性的值</span><span style="color: #008000;"><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">return</span>&nbsp;value;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">else</span>&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">return</span>&nbsp;"";<br />&nbsp;&nbsp;&nbsp;&nbsp;}<span style="color: #008000;">//</span><span style="color: #008000;">end&nbsp;getValue(<img src="http://www.blogjava.net/Images/dot.gif" alt="" />)</span><span style="color: #008000;"><br /></span><br />&nbsp;&nbsp;&nbsp;&nbsp;<br /><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">static</span>&nbsp;<span style="color: #0000ff;">void</span>&nbsp;main(String[]&nbsp;args)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(Configuration.getValue("aaa"));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(System.getProperty("user.dir"));<br /><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<span style="color: #008000;">//</span><span style="color: #008000;">end&nbsp;main()</span><span style="color: #008000;"><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<br />}<span style="color: #008000;">//</span><span style="color: #008000;">end&nbsp;class&nbsp;ReadConfigInfo</span></div><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><img src ="http://www.blogjava.net/gen-sky/aggbug/395869.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gen-sky/" target="_blank">星期五</a> 2013-02-28 18:08 <a href="http://www.blogjava.net/gen-sky/articles/spring3_email.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【找错题】 出除list集合中的数字</title><link>http://www.blogjava.net/gen-sky/articles/list.html</link><dc:creator>星期五</dc:creator><author>星期五</author><pubDate>Thu, 17 Jun 2010 07:36:00 GMT</pubDate><guid>http://www.blogjava.net/gen-sky/articles/list.html</guid><wfw:comment>http://www.blogjava.net/gen-sky/comments/323722.html</wfw:comment><comments>http://www.blogjava.net/gen-sky/articles/list.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gen-sky/comments/commentRss/323722.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gen-sky/services/trackbacks/323722.html</trackback:ping><description><![CDATA[<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008080;">&nbsp;1</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;main(String[]&nbsp;args)&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">String</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;list&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;ArrayList</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">String</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">();<br />
</span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.add(</span><span style="color: #000000;">"</span><span style="color: #000000;">a</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.add(</span><span style="color: #000000;">"</span><span style="color: #000000;">b</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.add(</span><span style="color: #000000;">"</span><span style="color: #000000;">c</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.add(</span><span style="color: #000000;">"</span><span style="color: #000000;">136</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.add(</span><span style="color: #000000;">"</span><span style="color: #000000;">14</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.add(</span><span style="color: #000000;">"</span><span style="color: #000000;">f</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;i</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">list.size();i</span><span style="color: #000000;">++</span><span style="color: #000000;">){<br />
</span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;str&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;list.get(i);<br />
</span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(isNumeric(str)){<br />
</span><span style="color: #008080;">13</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.remove(i);<br />
</span><span style="color: #008080;">14</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">15</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">16</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;i</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">list.size();i</span><span style="color: #000000;">++</span><span style="color: #000000;">){<br />
</span><span style="color: #008080;">17</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(list.get(i));<br />
</span><span style="color: #008080;">18</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">19</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">20</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">boolean</span><span style="color: #000000;">&nbsp;isNumeric(String&nbsp;str)&nbsp;{&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;判断字符串是否为数字</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">21</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Pattern&nbsp;pattern&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Pattern.compile(</span><span style="color: #000000;">"</span><span style="color: #000000;">[0-9]*</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">22</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Matcher&nbsp;isNum&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;pattern.matcher(str);<br />
</span><span style="color: #008080;">23</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">!</span><span style="color: #000000;">isNum.matches())&nbsp;{<br />
</span><span style="color: #008080;">24</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">false</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">25</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">26</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">true</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">27</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<img src ="http://www.blogjava.net/gen-sky/aggbug/323722.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gen-sky/" target="_blank">星期五</a> 2010-06-17 15:36 <a href="http://www.blogjava.net/gen-sky/articles/list.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转] 垃圾收集趣史(Garbage Collection )</title><link>http://www.blogjava.net/gen-sky/articles/GarbageCollection.html</link><dc:creator>星期五</dc:creator><author>星期五</author><pubDate>Thu, 03 Dec 2009 06:56:00 GMT</pubDate><guid>http://www.blogjava.net/gen-sky/articles/GarbageCollection.html</guid><wfw:comment>http://www.blogjava.net/gen-sky/comments/304621.html</wfw:comment><comments>http://www.blogjava.net/gen-sky/articles/GarbageCollection.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gen-sky/comments/commentRss/304621.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gen-sky/services/trackbacks/304621.html</trackback:ping><description><![CDATA[<div>
<h1>垃圾收集趣史</h1>
<div>
<p>本文发表于2004年2月《CSDN开发高手》</p>
</div>
<p>写作本文的初衷是想和大家分享垃圾收集（ Garbage Collection
）技术简单而有趣的发展史。动笔之前，我站在窗边，望了望正在小区里装运垃圾的清洁车。和生活中环卫工人们清运垃圾的工作相似，软件开发里的垃圾收集其实
就是一种自动打扫和清除内存垃圾的技术，它可以有效防范动态内存分配中可能发生的两个危险：因内存垃圾过多而引发的内存耗尽（这和生活垃圾堵塞排污管道的
危险并没有什么本质的不同），以及不恰当的内存释放所造成的内存非法引用（这类似于我们在生活中买到了一瓶已经过期三年的牛奶）。 </p>
<p>据历史学家们介绍，四千多年前的古埃及人已经在城市里建设了完善的排污和垃圾清运设施，一千多年前的中国人更是修筑了当时世界上保洁能力最强的都市
——长安。今天，当我们在软件开发中体验自动垃圾收集的便捷与舒适时，我们至少应当知道，这种拒绝杂乱、追求整洁的&#8220;垃圾收集&#8221;精神其实是人类自古以来就
已经具备了的。 </p>
<div>
<h3>拓荒时代</h3>
<p>国内的程序员大多是在 Java 语言中第一次感受到垃圾收集技术的巨大魅力的，许多人也因此把 Java
和垃圾收集看成了密不可分的整体。但事实上，垃圾收集技术早在 Java 语言问世前 30 多年就已经发展和成熟起来了， Java
语言所做的不过是把这项神奇的技术带到了广大程序员身边而已。 </p>
<p>如果一定要为垃圾收集技术找一个孪生兄弟，那么， Lisp 语言才是当之无愧的人选。 1960 年前后诞生于 MIT 的 Lisp
语言是第一种高度依赖于动态内存分配技术的语言： Lisp 中几乎所有数据都以&#8220;表&#8221;的形式出现，而&#8220;表&#8221;所占用的空间则是在堆中动态分配得到的。
Lisp 语言先天就具有的动态内存管理特性要求 Lisp 语言的设计者必须解决堆中每一个内存块的自动释放问题（否则， Lisp
程序员就必然被程序中不计其数的 free 或 delete
语句淹没），这直接导致了垃圾收集技术的诞生和发展——说句题外话，上大学时，一位老师曾告诉我们， Lisp
是对现代软件开发技术贡献最大的语言。我当时对这一说法不以为然：布满了圆括号，看上去像迷宫一样的 Lisp 语言怎么能比 C 语言或
Pascal
语言更伟大呢？不过现在，当我知道垃圾收集技术、数据结构技术、人工智能技术、并行处理技术、虚拟机技术、元数据技术以及程序员们耳熟能详的许多技术都起
源于 Lisp 语言时，我特别想向那位老师当面道歉，并收回我当时的幼稚想法。 </p>
<p>知道了 Lisp 语言与垃圾收集的密切关系，我们就不难理解，为什么垃圾收集技术的两位先驱者 J. McCarthy 和 M. L.
Minsky 同时也是 Lisp 语言发展史上的重要人物了。 J. McCarthy 是 Lisp 之父，他在发明 Lisp
语言的同时也第一次完整地描述了垃圾收集的算法和实现方式； M. L. Minsky 则在发展 Lisp
语言的过程中成为了今天好几种主流垃圾收集算法的奠基人——和当时不少技术大师的经历相似， J. McCarthy 和 M. L. Minsky
在许多不同的技术领域里都取得了令人艳羡的成就。也许，在 1960
年代那个软件开发史上的拓荒时代里，思维敏捷、意志坚定的研究者更容易成为无所不能的西部硬汉吧。 </p>
<p>在了解垃圾收集算法的起源之前，有必要先回顾一下内存分配的主要方式。我们知道，大多数主流的语言或运行环境都支持三种最基本的内存分配方式，它们分别是： </p>
<p>一、静态分配（ Static Allocation ）：静态变量和全局变量的分配形式。我们可以把静态分配的内存看成是家里的耐用家具。通常，它们无需释放和回收，因为没人会天天把大衣柜当作垃圾扔到窗外。 </p>
<p>二、自动分配（ Automatic Allocation
）：在栈中为局部变量分配内存的方法。栈中的内存可以随着代码块退出时的出栈操作被自动释放。这类似于到家中串门的访客，天色一晚就要各回各家，除了个别
不识时务者以外，我们一般没必要把客人捆在垃圾袋里扫地出门。 </p>
<p>三、动态分配（ Dynamic Allocation
）：在堆中动态分配内存空间以存储数据的方式。堆中的内存块好像我们日常使用的餐巾纸，用过了就得扔到垃圾箱里，否则屋内就会满地狼藉。像我这样的懒人做
梦都想有一台家用机器人跟在身边打扫卫生。在软件开发中，如果你懒得释放内存，那么你也需要一台类似的机器人——这其实就是一个由特定算法实现的垃圾收集
器。 </p>
<p>也就是说，下面提到的所有垃圾收集算法都是在程序运行过程中收集并清理废旧&#8220;餐巾纸&#8221;的算法，它们的操作对象既不是静态变量，也不是局部变量，而是堆中所有已分配内存块。 </p>
<div>
<h3>引用计数（ Reference Counting ）算法</h3>
<p>1960 年以前，人们为胚胎中的 Lisp 语言设计垃圾收集机制时，第一个想到的算法是引用计数算法。拿餐巾纸的例子来说，这种算法的原理大致可以描述为： </p>
<p>午餐时，为了把脑子里突然跳出来的设计灵感记下来，我从餐巾纸袋中抽出一张餐巾纸，打算在上面画出系统架构的蓝图。按照&#8220;餐巾纸使用规约之引用计数
版&#8221;的要求，画图之前，我必须先在餐巾纸的一角写上计数值 1
，以表示我在使用这张餐巾纸。这时，如果你也想看看我画的蓝图，那你就要把餐巾纸上的计数值加 1 ，将它改为 2 ，这表明目前有 2
个人在同时使用这张餐巾纸（当然，我是不会允许你用这张餐巾纸来擦鼻涕的）。你看完后，必须把计数值减 1
，表明你对该餐巾纸的使用已经结束。同样，当我将餐巾纸上的内容全部誊写到笔记本上之后，我也会自觉地把餐巾纸上的计数值减 1
。此时，不出意外的话，这张餐巾纸上的计数值应当是 0
，它会被垃圾收集器——假设那是一个专门负责打扫卫生的机器人——捡起来扔到垃圾箱里，因为垃圾收集器的惟一使命就是找到所有计数值为 0
的餐巾纸并清理它们。 </p>
<p>引用计数算法的优点和缺陷同样明显。这一算法在执行垃圾收集任务时速度较快，但算法对程序中每一次内存分配和指针操作提出了额外的要求（增加或减少
内存块的引用计数）。更重要的是，引用计数算法无法正确释放循环引用的内存块，对此， D. Hillis 有一段风趣而精辟的论述： </p>
<p>一天，一个学生走到 Moon 面前说：&#8220;我知道如何设计一个更好的垃圾收集器了。我们必须记录指向每个结点的指针数目。&#8221; Moon 耐心地给这位学生讲了下面这个故事：&#8220;一天，一个学生走到 Moon 面前说：&#8216;我知道如何设计一个更好的垃圾收集器了&#8230;&#8230;&#8217;&#8221; </p>
<p>D. Hillis
的故事和我们小时候常说的&#8220;从前有座山，山上有个庙，庙里有个老和尚&#8221;的故事有异曲同工之妙。这说明，单是使用引用计数算法还不足以解决垃圾收集中的所有
问题。正因为如此，引用计数算法也常常被研究者们排除在狭义的垃圾收集算法之外。当然，作为一种最简单、最直观的解决方案，引用计数算法本身具有其不可替
代的优越性。 1980 年代前后， D. P. Friedman ， D. S. Wise ， H. G. Baker
等人对引用计数算法进行了数次改进，这些改进使得引用计数算法及其变种（如延迟计数算法等）在简单的环境下，或是在一些综合了多种算法的现代垃圾收集系统
中仍然可以一展身手。 </p>
</div>
<div>
<h3>标记－清除（ Mark-Sweep ）算法</h3>
<p>第一种实用和完善的垃圾收集算法是 J. McCarthy 等人在 1960 年提出并成功地应用于 Lisp 语言的标记－清除算法。仍以餐巾纸为例，标记－清除算法的执行过程是这样的： </p>
<p>午餐过程中，餐厅里的所有人都根据自己的需要取用餐巾纸。当垃圾收集机器人想收集废旧餐巾纸的时候，它会让所有用餐的人先停下来，然后，依次询问餐
厅里的每一个人：&#8220;你正在用餐巾纸吗？你用的是哪一张餐巾纸？&#8221;机器人根据每个人的回答将人们正在使用的餐巾纸画上记号。询问过程结束后，机器人在餐厅里
寻找所有散落在餐桌上且没有记号的餐巾纸（这些显然都是用过的废旧餐巾纸），把它们统统扔到垃圾箱里。 </p>
<p>正如其名称所暗示的那样，标记－清除算法的执行过程分为&#8220;标记&#8221;和&#8220;清除&#8221;两大阶段。这种分步执行的思路奠定了现代垃圾收集算法的思想基础。与引用
计数算法不同的是，标记－清除算法不需要运行环境监测每一次内存分配和指针操作，而只要在&#8220;标记&#8221;阶段中跟踪每一个指针变量的指向——用类似思路实现的垃
圾收集器也常被后人统称为跟踪收集器（ Tracing Collector ） </p>
<p>伴随着 Lisp 语言的成功，标记－清除算法也在大多数早期的 Lisp
运行环境中大放异彩。尽管最初版本的标记－清除算法在今天看来还存在效率不高（标记和清除是两个相当耗时的过程）等诸多缺陷，但在后面的讨论中，我们可以
看到，几乎所有现代垃圾收集算法都是标记－清除思想的延续，仅此一点， J. McCarthy 等人在垃圾收集技术方面的贡献就丝毫不亚于他们在
Lisp 语言上的成就了。 </p>
</div>
<div>
<h3>复制（ Copying ）算法</h3>
<p>为了解决标记－清除算法在垃圾收集效率方面的缺陷， M. L. Minsky 于 1963 年发表了著名的论文&#8220;一种使用双存储区的
Lisp 语言垃圾收集器（ A LISP Garbage Collector Algorithm Using Serial Secondary
Storage ）&#8221;。 M. L. Minsky 在该论文中描述的算法被人们称为复制算法，它也被 M. L. Minsky 本人成功地引入到了
Lisp 语言的一个实现版本中。 </p>
<p>复制算法别出心裁地将堆空间一分为二，并使用简单的复制操作来完成垃圾收集工作，这个思路相当有趣。借用餐巾纸的比喻，我们可以这样理解 M. L. Minsky 的复制算法： </p>
<p>餐厅被垃圾收集机器人分成南区和北区两个大小完全相同的部分。午餐时，所有人都先在南区用餐（因为空间有限，用餐人数自然也将减少一半），用餐时可
以随意使用餐巾纸。当垃圾收集机器人认为有必要回收废旧餐巾纸时，它会要求所有用餐者以最快的速度从南区转移到北区，同时随身携带自己正在使用的餐巾纸。
等所有人都转移到北区之后，垃圾收集机器人只要简单地把南区中所有散落的餐巾纸扔进垃圾箱就算完成任务了。下一次垃圾收集的工作过程也大致类似，惟一的不
同只是人们的转移方向变成了从北区到南区。如此循环往复，每次垃圾收集都只需简单地转移（也就是复制）一次，垃圾收集速度无与伦比——当然，对于用餐者往
返奔波于南北两区之间的辛劳，垃圾收集机器人是决不会流露出丝毫怜悯的。 </p>
<p>M. L. Minsky
的发明绝对算得上一种奇思妙想。分区、复制的思路不仅大幅提高了垃圾收集的效率，而且也将原本繁纷复杂的内存分配算法变得前所未有地简明和扼要（既然每次
内存回收都是对整个半区的回收，内存分配时也就不用考虑内存碎片等复杂情况，只要移动堆顶指针，按顺序分配内存就可以了），这简直是个奇迹！不过，任何奇
迹的出现都有一定的代价，在垃圾收集技术中，复制算法提高效率的代价是人为地将可用内存缩小了一半。实话实说，这个代价未免也太高了一些。 </p>
<p>无论优缺点如何，复制算法在实践中都获得了可以与标记－清除算法相比拟的成功。除了 M. L. Minsky 本人在 Lisp
语言中的工作以外，从 1960 年代末到 1970 年代初， R. R. Fenichel 和 J. C. Yochelson 等人也相继在
Lisp 语言的不同实现中对复制算法进行了改进， S. Arnborg 更是成功地将复制算法应用到了 Simula 语言中。 </p>
<p>至此，垃圾收集技术的三大传统算法——引用计数算法、标记－清除算法和复制算法——都已在 1960
年前后相继问世，三种算法各有所长，也都存在致命的缺陷。从 1960
年代后期开始，研究者的主要精力逐渐转向对这三种传统算法进行改进或整合，以扬长避短，适应程序设计语言和运行环境对垃圾收集的效率和实时性所提出的更高
要求。 </p>
</div>
</div>
<div>
<h3>走向成熟</h3>
<p>从 1970
年代开始，随着科学研究和应用实践的不断深入，人们逐渐意识到，一个理想的垃圾收集器不应在运行时导致应用程序的暂停，不应额外占用大量的内存空间和
CPU
资源，而三种传统的垃圾收集算法都无法满足这些要求。人们必须提出更新的算法或思路，以解决实践中碰到的诸多难题。当时，研究者的努力目标包括： </p>
<p>第一，提高垃圾收集的效率。使用标记－清除算法的垃圾收集器在工作时要消耗相当多的 CPU 资源。早期的 Lisp
运行环境收集内存垃圾的时间竟占到了系统总运行时间的 40% ！——垃圾收集效率的低下直接造就了 Lisp
语言在执行速度方面的坏名声；直到今天，许多人还条件反射似地误以为所有 Lisp 程序都奇慢无比。 </p>
<p>第二，减少垃圾收集时的内存占用。这一问题主要出现在复制算法中。尽管复制算法在效率上获得了质的突破，但牺牲一半内存空间的代价仍然是巨大的。在计算机发展的早期，在内存价格以 KB 计算的日子里，浪费客户的一半内存空间简直就是在变相敲诈或拦路打劫。 </p>
<p>第三，寻找实时的垃圾收集算法。无论执行效率如何，三种传统的垃圾收集算法在执行垃圾收集任务时都必须打断程序的当前工作。这种因垃圾收集而造成的
延时是许多程序，特别是执行关键任务的程序没有办法容忍的。如何对传统算法进行改进，以便实现一种在后台悄悄执行，不影响——或至少看上去不影响——当前
进程的实时垃圾收集器，这显然是一件更具挑战性的工作。 </p>
<p>研究者们探寻未知领域的决心和研究工作的进展速度同样令人惊奇：在 1970 年代到 1980
年代的短短十几年中，一大批在实用系统中表现优异的新算法和新思路脱颖而出。正是因为有了这些日趋成熟的垃圾收集算法，今天的我们才能在 Java 或
.NET 提供的运行环境中随心所欲地分配内存块，而不必担心空间释放时的风险。 </p>
<div>
<h3>标记－整理（ Mark-Compact ）算法</h3>
<p>标记－整理算法是标记－清除算法和复制算法的有机结合。把标记－清除算法在内存占用上的优点和复制算法在执行效率上的特长综合起来，这是所有人都希
望看到的结果。不过，两种垃圾收集算法的整合并不像 1 加 1 等于 2 那样简单，我们必须引入一些全新的思路。 1970 年前后， G. L.
Steele ， C. J. Cheney 和 D. S. Wise 等研究者陆续找到了正确的方向，标记－整理算法的轮廓也逐渐清晰了起来： </p>
<p>在我们熟悉的餐厅里，这一次，垃圾收集机器人不再把餐厅分成两个南北区域了。需要执行垃圾收集任务时，机器人先执行标记－清除算法的第一个步骤，为
所有使用中的餐巾纸画好标记，然后，机器人命令所有就餐者带上有标记的餐巾纸向餐厅的南面集中，同时把没有标记的废旧餐巾纸扔向餐厅北面。这样一来，机器
人只消站在餐厅北面，怀抱垃圾箱，迎接扑面而来的废旧餐巾纸就行了。 </p>
<p>实验表明，标记－整理算法的总体执行效率高于标记－清除算法，又不像复制算法那样需要牺牲一半的存储空间，这显然是一种非常理想的结果。在许多现代的垃圾收集器中，人们都使用了标记－整理算法或其改进版本。 </p>
</div>
<div>
<h3>增量收集（ Incremental Collecting ）算法</h3>
<p>对实时垃圾收集算法的研究直接导致了增量收集算法的诞生。 </p>
<p>最初，人们关于实时垃圾收集的想法是这样的：为了进行实时的垃圾收集，可以设计一个多进程的运行环境，比如用一个进程执行垃圾收集工作，另一个进程执行程序代码。这样一来，垃圾收集工作看上去就仿佛是在后台悄悄完成的，不会打断程序代码的运行。 </p>
<p>在收集餐巾纸的例子中，这一思路可以被理解为：垃圾收集机器人在人们用餐的同时寻找废弃的餐巾纸并将它们扔到垃圾箱里。这个看似简单的思路会在设计
和实现时碰上进程间冲突的难题。比如说，如果垃圾收集进程包括标记和清除两个工作阶段，那么，垃圾收集器在第一阶段中辛辛苦苦标记出的结果很可能被另一个
进程中的内存操作代码修改得面目全非，以至于第二阶段的工作没有办法开展。 </p>
<p>M. L. Minsky 和 D. E. Knuth 对实时垃圾收集过程中的技术难点进行了早期的研究， G. L. Steele 于
1975 年发表了题为&#8220;多进程整理的垃圾收集（ Multiprocessing compactifying garbage
collection ）&#8221;的论文，描述了一种被后人称为&#8220; Minsky-Knuth-Steele 算法&#8221;的实时垃圾收集算法。 E. W.
Dijkstra ， L. Lamport ， R. R. Fenichel 和 J. C. Yochelson
等人也相继在此领域做出了各自的贡献。 1978 年， H. G. Baker 发表了&#8220;串行计算机上的实时表处理技术（ List
Processing in Real Time on a Serial Computer
）&#8221;一文，系统阐述了多进程环境下用于垃圾收集的增量收集算法。 </p>
<p>增量收集算法的基础仍是传统的标记－清除和复制算法。增量收集算法通过对进程间冲突的妥善处理，允许垃圾收集进程以分阶段的方式完成标记、清理或复
制工作。详细分析各种增量收集算法的内部机理是一件相当繁琐的事情，在这里，读者们需要了解的仅仅是： H. G. Baker
等人的努力已经将实时垃圾收集的梦想变成了现实，我们再也不用为垃圾收集打断程序的运行而烦恼了。 </p>
</div>
<div>
<h3>分代收集（ Generational Collecting ）算法</h3>
<p>和大多数软件开发技术一样，统计学原理总能在技术发展的过程中起到强力催化剂的作用。 1980
年前后，善于在研究中使用统计分析知识的技术人员发现，大多数内存块的生存周期都比较短，垃圾收集器应当把更多的精力放在检查和清理新分配的内存块上。这
个发现对于垃圾收集技术的价值可以用餐巾纸的例子概括如下： </p>
<p>如果垃圾收集机器人足够聪明，事先摸清了餐厅里每个人在用餐时使用餐巾纸的习惯——比如有些人喜欢在用餐前后各用掉一张餐巾纸，有的人喜欢自始至终
攥着一张餐巾纸不放，有的人则每打一个喷嚏就用去一张餐巾纸——机器人就可以制定出更完善的餐巾纸回收计划，并总是在人们刚扔掉餐巾纸没多久就把垃圾捡
走。这种基于统计学原理的做法当然可以让餐厅的整洁度成倍提高。 </p>
<p>D. E. Knuth ， T. Knight ， G. Sussman 和 R. Stallman
等人对内存垃圾的分类处理做了最早的研究。 1983 年， H. Lieberman 和 C. Hewitt
发表了题为&#8220;基于对象寿命的一种实时垃圾收集器（ A real-time garbage collector based on the
lifetimes of objects ）&#8221;的论文。这篇著名的论文标志着分代收集算法的正式诞生。此后，在 H. G. Baker ， R.
L. Hudson ， J. E. B. Moss 等人的共同努力下，分代收集算法逐渐成为了垃圾收集领域里的主流技术。 </p>
<p>分代收集算法通常将堆中的内存块按寿命分为两类，年老的和年轻的。垃圾收集器使用不同的收集算法或收集策略，分别处理这两类内存块，并特别地把主要
工作时间花在处理年轻的内存块上。分代收集算法使垃圾收集器在有限的资源条件下，可以更为有效地工作——这种效率上的提高在今天的 Java
虚拟机中得到了最好的证明。 </p>
</div>
</div>
<div>
<h3>应用浪潮</h3>
<p>Lisp 是垃圾收集技术的第一个受益者，但显然不是最后一个。在 Lisp
语言之后，许许多多传统的、现代的、后现代的语言已经把垃圾收集技术拉入了自己的怀抱。随便举几个例子吧：诞生于 1964 年的 Simula
语言， 1969 年的 Smalltalk 语言， 1970 年的 Prolog 语言， 1973 年的 ML 语言， 1975 年的
Scheme 语言， 1983 年的 Modula-3 语言， 1986 年的 Eiffel 语言， 1987 年的 Haskell
语言&#8230;&#8230;它们都先后使用了自动垃圾收集技术。当然，每一种语言使用的垃圾收集算法可能不尽相同，大多数语言和运行环境甚至同时使用了多种垃圾收集算法。但
无论怎样，这些实例都说明，垃圾收集技术从诞生的那一天起就不是一种曲高和寡的&#8220;学院派&#8221;技术。 </p>
<p>对于我们熟悉的 C 和 C++ 语言，垃圾收集技术一样可以发挥巨大的功效。正如我们在学校中就已经知道的那样， C 和 C++
语言本身并没有提供垃圾收集机制，但这并不妨碍我们在程序中使用具有垃圾收集功能的函数库或类库。例如，早在 1988 年， H. J. Boehm
和 A. J. Demers 就成功地实现了一种使用保守垃圾收集算法（ Conservative GC Algorithmic
）的函数库（参见 <a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc">http://www.hpl.hp.com/personal/Hans_Boehm/gc </a>）。我们可以在 C 语言或 C++ 语言中使用该函数库完成自动垃圾收集功能，必要时，甚至还可以让传统的 C/C++ 代码与使用自动垃圾收集功能的 C/C++ 代码在一个程序里协同工作。 </p>
<p>1995 年诞生的 Java 语言在一夜之间将垃圾收集技术变成了软件开发领域里最为流行的技术之一。从某种角度说，我们很难分清究竟是
Java 从垃圾收集中受益，还是垃圾收集技术本身借 Java 的普及而扬名。值得注意的是，不同版本的 Java
虚拟机使用的垃圾收集机制并不完全相同， Java 虚拟机其实也经过了一个从简单到复杂的发展过程。在 Java 虚拟机的 1.4.1
版中，人们可以体验到的垃圾收集算法就包括分代收集、复制收集、增量收集、标记－整理、并行复制（ Parallel Copying ）、并行清除（
Parallel Scavenging ）、并发（ Concurrent ）收集等许多种， Java
程序运行速度的不断提升在很大程度上应该归功于垃圾收集技术的发展与完善。 </p>
<p>尽管历史上已经有许多包含垃圾收集技术的应用平台和操作系统出现，但 Microsoft .NET
却是第一种真正实用化的、包含了垃圾收集机制的通用语言运行环境。事实上， .NET 平台上的所有语言，包括 C# 、 Visual Basic
.NET 、 Visual C++ .NET 、 J# 等等，都可以通过几乎完全相同的方式使用 .NET
平台提供的垃圾收集机制。我们似乎可以断言， .NET
是垃圾收集技术在应用领域里的一次重大变革，它使垃圾收集技术从一种单纯的技术变成了应用环境乃至操作系统中的一种内在文化。这种变革对未来软件开发技术
的影响力也许要远远超过 .NET 平台本身的商业价值。 </p>
</div>
<div>
<h3>大势所趋</h3>
<p>今天，致力于垃圾收集技术研究的人们仍在不懈努力，他们的研究方向包括分布式系统的垃圾收集、复杂事务环境下的垃圾收集、数据库等特定系统的垃圾收集等等。 </p>
<p>但在程序员中间，仍有不少人对垃圾收集技术不屑一顾，他们宁愿相信自己逐行编写的 free 或 delete 命令，也不愿把垃圾收集的重任交给那些在他们看来既蠢又笨的垃圾收集器。 </p>
<p>我个人认为，垃圾收集技术的普及是大势所趋，这就像生活会越来越好一样毋庸置疑。今天的程序员也许会因为垃圾收集器要占用一定的 CPU
资源而对其望而却步，但二十多年前的程序员还曾因为高级语言速度太慢而坚持用机器语言写程序呢！在硬件速度日新月异的今天，我们是要吝惜那一点儿时间损耗
而踟躇不前，还是该坚定不移地站在代码和运行环境的净化剂——垃圾收集的一边呢？ </p>
</div>
<p>[王咏刚，2003年12月]</p>
</div>
<img src ="http://www.blogjava.net/gen-sky/aggbug/304621.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gen-sky/" target="_blank">星期五</a> 2009-12-03 14:56 <a href="http://www.blogjava.net/gen-sky/articles/GarbageCollection.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>垃圾回收工作机制                                   学习自《Java程序员   上班那点事儿》</title><link>http://www.blogjava.net/gen-sky/articles/285795.html</link><dc:creator>星期五</dc:creator><author>星期五</author><pubDate>Tue, 07 Jul 2009 05:23:00 GMT</pubDate><guid>http://www.blogjava.net/gen-sky/articles/285795.html</guid><wfw:comment>http://www.blogjava.net/gen-sky/comments/285795.html</wfw:comment><comments>http://www.blogjava.net/gen-sky/articles/285795.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gen-sky/comments/commentRss/285795.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gen-sky/services/trackbacks/285795.html</trackback:ping><description><![CDATA[<p><strong>4.5&nbsp;内存垃圾回收问题</strong></p>
<p><strong>那本谭浩强主编的Java入门教材说：</strong></p>
<p><font face="楷体_GB2312">&#8230;&#8230;</font></p>
<p><font face="楷体_GB2312">1、简单性</font></p>
<p><font face="楷体_GB2312">设计Java语言的出发点就是容易编程，不需要深奥的知识。Java语言的风格十分接近C++语言，但要比C++简单得多。Java舍弃了一些不常用的、难以理解的、容易混淆的成分，如运算符重载、多继承等。增加了自动垃圾搜集功能，用于回收不再使用的内存区域。这不但使程序易于编写，而且大大减少了由于内存分配而引发的问题。</font></p>
<p><font face="楷体_GB2312">&#8230;&#8230;</font></p>
<p>这样类似的描述出现在众多的Java入门级教材中，非常容易让人们忽略了内存垃圾回收的问题，其实Java的垃圾回收问还是需要关注一下的。这个问题在招聘单位的笔试题中出现的频率也比较高，我们需要好好的研究一下Java的垃圾回收机制。</p>
<p><strong>4.5.1&nbsp;什么是内存垃圾，哪些内存符合垃圾的标准</strong></p>
<p>我们在前面讲过了，堆是一个"运行时"数据区，是通过"new"等指令建立的，Java的堆是由Java的垃圾回收机制来负责处理的，堆是动态分配内存大小，垃圾收集器可以自动回收不再使用的内存空间。</p>
<p>也就是说，所谓的"内存垃圾"是指在堆上开辟的内存空间在不用的时候就变成了"垃圾"。</p>
<p>C++或其他程序设计语言中，必须由程序员自行声明产生和回收，否则其中的资源将消耗，造成资源的浪费甚至死机。但手工回收内存往往是一项复杂而艰巨的工作。因为要预先确定占用的内存空间是否应该被回收是非常困难的！如果一段程序不能回收内存空间，而且在程序运行时系统中又没有了可以分配的内存空间时，这段程序就只能崩溃。</p>
<p>Java和C++相比的优势在于，这部分"垃圾"可以被Java
虚拟机（JVM）中的一个程序发现并自动清除掉，而不用程序员自己想着"delete"了。</p>
<p>Java语言提供了一个系统级的线程，即垃圾收集器线程（Garbage Collection
Thread），来跟踪每一块分配出去的内存空间，当JVM处于空闲循环时，自动回收每一块可以回收的内存。</p>
<p><strong>4.5.1.1&nbsp;垃圾回收工作机制</strong></p>
<p>垃圾收集器线程它是一种低优先级的线程，它必须在一个Java程序的运行过程中出现内存空闲的时候才去进行回收处理。</p>
<p>垃圾收集器系统有其判断内存块是否需要回收的判断标准的。垃圾收集器完全是自动被执行的，它不能被强制执行，即使程序员能明确地判断出某一块内存应该被回收了，也不能强制执行垃圾回收程序进行垃圾回收。</p>
<p>程序员可以做的只有调用"System.gc()"来"建议"执行垃圾收集器程序，但是这个垃圾收集程序什么时候被执行以及是否被执行了，都是不不能控制的。但是虽然垃圾收集器是低优先级的线程，却在系统内存可用量过低时，它仍然可能会突发地执行来挽救系统。</p>
<p><strong>4.5.1.2&nbsp;哪些符合"垃圾"标准</strong></p>
<p>如果想了解JVM的垃圾回收，就必须要知道JVM垃圾回收的标准。</p>
<p>垃圾收集器的"垃圾"标准：对象已经不能被程序中的其他程序所引用的时候，那么这个对象的内存空间已经没有用了。</p>
<p>比如当一个方法执行完毕时，在这个方法中声明的对象就超出其声明周期，这时候就可以被当作垃圾收集了，只有当这个方法被再次被调用时才会被重新创建。</p>
<p>例如：</p>
<table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0">
    <tbody>
        <tr>
            <td bgcolor="#e6e6e6">
            <pre>&#8230;&#8230;<br />
            public void function(){<br />
            OBJ obj=new OBJ();<br />
            &#8230;&#8230;<br />
            }<br />
            &#8230;&#8230;<br />
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<p>另外还可以将对象的引用变量初始化为null值，也可以来暗示垃圾收集器来收集该对象。</p>
<p>例如：</p>
<table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0">
    <tbody>
        <tr>
            <td bgcolor="#e6e6e6">
            <pre>&#8230;&#8230;<br />
            OBJ obj=new OBJ();<br />
            Obj=null;<br />
            &#8230;&#8230;<br />
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<p>
</p>
<p><strong>finalize()在该对象垃圾回收前调用</strong></p>
<p>垃圾收集器跟踪每一个对象，把那些不可到达的对象占有的内存空间收集起来，并且在每次进行垃圾收集之前，垃圾收集器都会调用一下finalize()方法。Java语言允许程序员给任何对象添加finalize(
)方法，但也不能过分依赖该方法对系统资源的回收和再利用，因为这个方法调用后的执行结果是不可预知的。对于任何给定对象，Java 虚拟机最多只调用一次
finalize 方法。 </p>
<p>我们用这个程序来演示一下：</p>
<table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0">
    <tbody>
        <tr>
            <td bgcolor="#e6e6e6">
            <pre>public class finalizeTest{<br />
            public static void main( String[] args ){<br />
            &nbsp;finalizeTest ft=new finalizeTest();<br />
            &nbsp;ft.loading();<br />
            &nbsp;byte bs[]=new byte[1450000];<br />
            }<br />
            public void loading(){<br />
            &nbsp;test t=new test();<br />
            &nbsp;t.callme();<br />
            }<br />
            }<br />
            class test{<br />
            protected void finalize(){<br />
            System.out.println("call finalize");<br />
            }<br />
            public void callme(){<br />
            System.out.println("callme");<br />
            }<br />
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
我们在命令行中键入如下命令：<br />
<table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0">
    <tbody>
        <tr>
            <td bgcolor="#e6e6e6">
            <pre>java -Xmx1k finalizeTest</pre>
            </td>
        </tr>
    </tbody>
</table>
程序运行结果如图 3
10所示。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img src="http://www.blogjava.net/images/blogjava_net/gen-sky/113425571.jpg" alt="" border="0" /><br />
<p>这时候，我们将JVM所许可使用的最大内存设置成"1k"，当内存被占满前JVM会首先去进行内存回收，于是失去活动的"test"对象被回收，在回收前调用了"finalize()"。<br />
</p>
<p><strong>4.5.2&nbsp;JVM垃圾回收的相关知识</strong></p>
<p>JVM使用的是分代垃圾回收的方式，主要是因为在程序运行的时候会有如下特点：</p>
<p>大多数对象在创建后很快就没有对象使用它了。</p>
<p>大多数在一直被使用的对象很少再去引用新创建的对象。</p>
<p>因此就将Java对象分为"年轻"对象和"年老"对象，JVM将内存堆（Heap）分为两个区域，一个是"年轻"区，另一个是"老"区，Java将这两个区域分别称作是"新生代"和"老生代"。</p>
<p>"新生代"区域中，绝大多数新创建的对象都存放在这个区域里，此区域一般来说较小而且垃圾回收频率较高，同时因为"新生代"采用的算法和其存放的对象的特点，使该区域垃圾回收的效率也非常高。</p>
<p>而"老生代"区域中存放的是在"新生代"中生存了较长时间的对象，这些对象将被转移到"老生代"区。这个区域一般要大一些而且增长的速度相对于"新生代"要慢一些，"老生代"垃圾回收的执行频率也会低很多。</p>
<p>由于JVM在垃圾回收处理时会消耗一定的系统资源，因此有时候通过JVM启动的时候添加相关参数来控制"新生代"区域的大小，来调整垃圾回收处理的频率非常有用。以便于我们更合理的利用系统资源。</p>
<p>"新生代"区域设置参数是"-Xmn"，用这个参数可以制定"新生代"区域的大小。</p>
<p>我们来举一个例子说明：</p>
<p>我们就用系统自带的程序作为例子，在命令行上键入如下指令：</p>
<table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0">
    <tbody>
        <tr>
            <td bgcolor="#e6e6e6">
            <pre>CD C:"java"demo"jfc"SwingSet2[回车]<br />
            C:"java"demo"jfc"SwingSet2&gt;java -jar -verbose:gc<br />
            -Xmn4m XX:+PrintGCDetails SwingSet2.jar[回车]<br />
            </pre>
            </td>
        </tr>
    </tbody>
</table>
上面加入了一个新的参数"XX:+PrintGCDetails"，这个参数能够打印出GC的详细信息。屏幕输出如下（节选）：<br />
<table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0">
    <tbody>
        <tr>
            <td bgcolor="#e6e6e6">
            <pre>[GC [DefNew: 3469K-&gt;84K(3712K), 0.0007778 secs] <br />
            23035K-&gt;19679K(28728K), 0.0009191 secs]<br />
            [GC [DefNew: 3284K-&gt;171K(3712K), 0.0007283 secs] <br />
            22878K-&gt;19766K(28728K), 0.0008669 secs]<br />
            [GC [DefNew: 3476K-&gt;260K(3712K), 0.0008504 secs] <br />
            23071K-&gt;19855K(28728K), 0.0009862 secs]<br />
            [GC [DefNew: 3502K-&gt;87K(3712K), 0.0009267 secs] <br />
            23096K-&gt;19682K(28728K), 0.0010610 secs]</pre>
            </td>
        </tr>
    </tbody>
</table>
<p>我们需要解释一下输出的详细内容的意思，拿第一行输出来说：</p>
<p>"DefNew: 3469K-&gt;84K(3712K), 0.0007778
secs"是指"新生代"的垃圾回收情况，这里的意思是从占用3469K内存空间变为84K内存空间，用时0.0007778秒。</p>
<p>"23035K-&gt;19679K(28728K), 0.0009191
secs"是指总体GC的回收情况，整体堆空间占用从23035K降低到19679K的水平，用时0.0009191秒。</p>
<p>那么，这时候我们在将"新生代"的内存设为8M，并把堆的最大可控值设定为32M，再去执行，键入如下指令：</p>
<table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0">
    <tbody>
        <tr>
            <td bgcolor="#e6e6e6">
            <pre>java -jar -verbose:gc -Xmn8m -Xmx32m <br />
            XX:+PrintGCDetails SwingSet2.jar[回车]</pre>
            </td>
        </tr>
    </tbody>
</table>
得到的结果如下（节选）：<br />
<table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0">
    <tbody>
        <tr>
            <td bgcolor="#e6e6e6">
            <pre>[GC [DefNew: 6633K-&gt;6633K(7424K), 0.0000684 secs]<br />
            [Tenured: 18740K-&gt;18820K(24576K), 0.0636505 secs] <br />
            25374K-&gt;18820K(32000K), 0.0639274 secs]<br />
            [GC [DefNew: 6646K-&gt;6646K(7424K), 0.0002581 secs]<br />
            [Tenured: 18820K-&gt;18884K(24576K), 0.0651957 secs] <br />
            25467K-&gt;18884K(32000K), 0.0658804 secs]<br />
            [GC [DefNew: 6611K-&gt;6611K(7424K), 0.0000668 secs]<br />
            [Tenured: 18884K-&gt;18505K(24576K), 0.0931406 secs] </pre>
            <pre>25496K-&gt;18505K(32000K), 0.0934295 secs]</pre>
            </td>
        </tr>
    </tbody>
</table>
<p><font face="楷体_GB2312">这个结果说明：</font></p>
<p><font face="楷体_GB2312">"[DefNew: 6633K-&gt;6633K(7424K), 0.0000684
secs]"是指"新生代"的垃圾回收情况，这里的意思是从占用6633K内存空间变为6633K内存空间，用时0.
0000684秒。<br />
"25374K-&gt;18820K(32000K), 0.0639274
secs"是指总体GC的回收情况，整体堆空间占用从25374K降低到18820K的水平，用时0. 0639274秒。<br />
"[Tenured:
18740K-&gt;18820K(24576K), 0.0636505
secs]"是指"老生代"GC的回收情况，整体堆空间占用从18740K降低到18820K的水平，用时0.0009012秒。</font></p>
<p>通过这些参数的调整我们可以看到在处理垃圾收集问题时，从垃圾回收的频率是时间方面的变化，我们可以根据不同程序的不同情况予以调整。</p>
<p>最后有必要提一下GC的相关参数：</p>
<p><font face="楷体_GB2312">-XX:+PrintGCDetails
显示GC的详细信息<br />
-XX:+PrintGCApplicationConcurrentTime
打印应用执行的时间<br />
-XX:+PrintGCApplicationStoppedTime
打印应用被暂停的时间<br />
注：":"后的"+"号表示开启此选项,如果是"-"号那么表示关闭此选项。</font></p>
&nbsp;<br />
<img src ="http://www.blogjava.net/gen-sky/aggbug/285795.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gen-sky/" target="_blank">星期五</a> 2009-07-07 13:23 <a href="http://www.blogjava.net/gen-sky/articles/285795.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>内存控制效率优化的启示     学习自《Java 程序员   上班那点事儿》</title><link>http://www.blogjava.net/gen-sky/articles/285791.html</link><dc:creator>星期五</dc:creator><author>星期五</author><pubDate>Tue, 07 Jul 2009 05:19:00 GMT</pubDate><guid>http://www.blogjava.net/gen-sky/articles/285791.html</guid><wfw:comment>http://www.blogjava.net/gen-sky/comments/285791.html</wfw:comment><comments>http://www.blogjava.net/gen-sky/articles/285791.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gen-sky/comments/commentRss/285791.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gen-sky/services/trackbacks/285791.html</trackback:ping><description><![CDATA[启示一：String和StringBuffer的不同之处<br />
<p>相信大家都知道String和StringBuffer之间是有区别的，但究竟它们之间到底区别在哪里？我们就再本小节中一探究竟，看看能给我们些什么启示。还是刚才那个程序，我们把它改一改，将本程序中的String进行无限次的累加，看看什么时候抛出内存超限的异常，程序如下所示：</p>
<table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0">
    <tbody>
        <tr>
            <td bgcolor="#e6e6e6">
            <pre>public class MemoryTest{<br />
            <br />
            public static void main(String args[]){<br />
            <br />
            String s="abcdefghijklmnop";<br />
            <br />
            System.out.print("当前虚拟机最大可用内存为:");<br />
            <br />
            System.out.println(Runtime.getRuntime().maxMemory()/1024/1024+"M");<br />
            <br />
            System.out.print("循环前，虚拟机已占用内存:");<br />
            <br />
            System.out.println(Runtime.getRuntime().totalMemory()/1024/1024+"M");<br />
            <br />
            int count = 0;<br />
            <br />
            while(true){<br />
            <br />
            try{<br />
            <br />
            s+=s;<br />
            <br />
            count++;<br />
            <br />
            }<br />
            <br />
            catch(Error o){<br />
            <br />
            System.out.println("循环次数:"+count);<br />
            <br />
            System.out.println("String实际字节数:"+s.length()/1024/1024+"M");<br />
            <br />
            System.out.print("循环后，已占用内存:");<br />
            <br />
            System.out.println(Runtime.getRuntime().totalMemory()/1024/1024+"M");<br />
            <br />
            System.out.println("Catch到的错误:"+o);<br />
            <br />
            break;<br />
            <br />
            }<br />
            <br />
            }<br />
            <br />
            }<br />
            <br />
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
程序运行后，果然不一会儿的功夫就报出了异常，如图
3 3所示。 <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; <img alt="" src="http://www.blogjava.net/images/blogjava_net/gen-sky/111125320.jpg" width="512" height="262" /> <br />
<p>我们注意到，在String的实际字节数只有8M的情况下，循环后已占内存数竟然已经达到了63.56M。这说明，String这个对象的实际占用内存数量与其自身的字节数不相符。于是，在循环19次的时候就已经报"OutOfMemoryError"的错误了。</p>
<p>因此，应该少用String这东西，特别是
String的"+="操作，不仅原来的String对象不能继续使用，而且又要产生多个新对象，因此会较高的占用内存。</p>
<p>所以必须要改用StringBuffer来实现相应目的，下面是改用StringBuffer来做一下测试：</p>
<table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0">
    <tbody>
        <tr>
            <td bgcolor="#e6e6e6">
            <pre>public class MemoryTest{<br />
            <br />
            public static void main(String args[]){<br />
            <br />
            StringBuffer s=new StringBuffer("abcdefghijklmnop");<br />
            <br />
            System.out.print("当前虚拟机最大可用内存为:");<br />
            <br />
            System.out.println(Runtime.getRuntime().maxMemory()/1024/1024+"M");<br />
            <br />
            System.out.print("循环前，虚拟机已占用内存:");<br />
            <br />
            System.out.println(Runtime.getRuntime().totalMemory()/1024/1024+"M");<br />
            <br />
            int count = 0;<br />
            <br />
            while(true){<br />
            <br />
            try{<br />
            <br />
            s.append(s);<br />
            <br />
            count++;<br />
            <br />
            }<br />
            <br />
            catch(Error o){<br />
            <br />
            System.out.println("循环次数:"+count);<br />
            <br />
            System.out.println("String实际字节数:"+s.length()/1024/1024+"M");<br />
            <br />
            System.out.println("循环后，已占用内存:");<br />
            <br />
            System.out.println(Runtime.getRuntime().totalMemory()/1024/1024+"M");<br />
            <br />
            System.out.println("Catch到的错误:"+o);<br />
            <br />
            break;<br />
            <br />
            }<br />
            <br />
            }<br />
            <br />
            }<br />
            <br />
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
我们将String改为StringBuffer以后，在运行时得到了如下结果，如图
3 4所示。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img src="http://www.blogjava.net/images/blogjava_net/gen-sky/111227471.jpg" alt="" border="0" /><br />
这次我们发现，当StringBuffer所占用的实际字节数为"16M"的时候才产生溢出，整整比上一个程序的String实际字节数"8M"多了一倍。<br />
<p><strong>启示2：用"-Xmx"参数来提高内存可控制量</strong></p>
<p>前面我们介绍过"-Xmx"这个参数的用法，如果我们还是处理刚才的那个用StringBuffer的Java程序，我们用"-Xmx1024m"来启动它，看看它的循环次数有什么变化。</p>
<p>输入如下指令：</p>
<table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0">
    <tbody>
        <tr>
            <td bgcolor="#e6e6e6">
            <pre>java -mx1024m MemoryTest</pre>
            </td>
        </tr>
    </tbody>
</table>
得到结果如图 3 5所示。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img src="http://www.blogjava.net/images/blogjava_net/gen-sky/111628142.jpg" alt="" border="0" /><br />
<p>那么通过使用"-Xmx"参数将其可控内存量扩大至1024M后，那么这个程序到了1G的时候才内存超限，从而使内存的可控性提高了。</p>
<p>但扩大内存使用量永远不是最终的解决方案，如果你的程序没有去更加的优化，早晚还是会超限的。</p>
<p><strong>启示3：二维数组比一维数组占用更多内存空间</strong></p>
<p>对于内存占用的问题还有一个地方值得我们注意，就是二维数组的内存占用问题。</p>
<p>有时候我们一厢情愿的认为：</p>
<p>二维数组的占用内存空间多无非就是二维数组的实际数组元素数比一维数组多而已，那么二维数组的所占空间，一定是实际申请的元素数而已。</p>
<p>但是，事实上并不是这样的，对于一个二维数组而言，它所占用的内存空间要远远大于它开辟的数组元素数。下面我们来看一个一维数组程序的例子：</p>
<table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0">
    <tbody>
        <tr>
            <td bgcolor="#e6e6e6">
            <pre>public class MemFor{<br />
            <br />
            public static void main (String[] args) {<br />
            <br />
            try{<br />
            <br />
            int len=1024*1024*2;&nbsp;&nbsp; //设定循环次数<br />
            <br />
            byte [] abc=new byte[len];<br />
            <br />
            for (int i=0;i&lt;len;i++){<br />
            <br />
            abc[i]=(byte)i;<br />
            <br />
            }<br />
            <br />
            System.out.print("已占用内存:");&nbsp;<br />
            <br />
            System.out.println(<br />
            <br />
            Runtime.getRuntime().totalMemory()/1024/1024+"M");<br />
            <br />
            }<br />
            <br />
            catch(Error e){<br />
            <br />
            }<br />
            <br />
            }<br />
            <br />
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
这个程序是开辟了"1024*1024*2"即2M的数组元素的一维数组，运行这个程序得到的结果如图
3 6所示，程序运行结果提示"已占用内存：3M"。<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<img src="http://www.blogjava.net/images/blogjava_net/gen-sky/111832715.jpg" alt="" border="0" /> <br />
<br />
<br />
<p>我们再将这个程序进行修改，改为一个二维数组，这个二维数组的元素数量我们也尽量的和上一个一维数组的元素数量保持一致。</p>
<table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0">
    <tbody>
        <tr>
            <td bgcolor="#e6e6e6">
            <pre>public class MemFor{<br />
            <br />
            public static void main (String[] args) {<br />
            <br />
            try{<br />
            <br />
            int len=1024*1024;&nbsp; //设定循环次数<br />
            <br />
            byte [][] abc=new byte[len][2];<br />
            <br />
            for (int i=0;i&lt;len;i++){<br />
            <br />
            abc[i][0]=(byte)i;<br />
            <br />
            abc[i][1]=(byte)i;<br />
            <br />
            }<br />
            <br />
            System.out.print("已占用内存:");&nbsp;<br />
            <br />
            System.out.println(<br />
            <br />
            Runtime.getRuntime().totalMemory()/1024/1024+"M");<br />
            <br />
            }<br />
            <br />
            catch(Error e){<br />
            <br />
            }<br />
            <br />
            }<br />
            <br />
            }<br />
            <br />
            </pre>
            </td>
        </tr>
    </tbody>
</table>
当我们把申请的元素数量未变，只是将二维数组的行数定为"1024*1024"列数定为"2"，和刚才的那个一维数组"1024*1024*2"的数量完全一致，但我们得到的运算结果如图
3 7所示，竟然占用达到了29M的空间。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img src="http://www.blogjava.net/images/blogjava_net/gen-sky/111922889.jpg" alt="" border="0" /><br />
我们姑且不管造成这种情况的原因，我们只要知道一点就够了，那就是"二维数组占内存"。所以，在编写程序的时候要注意，能不用二维数组的地方尽量用一维数组，要求内存占用小的地方尽量用一维数组。<br />
<br />
<br />
<br />
<br />
<p><strong>4.4.4&nbsp;启示4：用HashMap提高内存查询速度</strong></p>
<p><strong>田富鹏主编的《大学计算机应用基础》中是这样描述内存的：</strong></p>
<p><font face="楷体_GB2312">&#8230;&#8230;</font></p>
<p><font face="楷体_GB2312">DRAM：即内存条。常说的内存并不是内部存储器，而是DRAM。</font></p>
<p><font face="楷体_GB2312">&#8230;&#8230;CPU的运行速度很快，而外部存储器的读取速度相对来说就很慢，如果CPU需要用到的数据总是从外部存储器中读取，由于外部设备很慢，&#8230;&#8230;，CPU可能用到的数据预先读到DRAM中，CPU产生的临时数据也暂时存放在DRAM中，这样的结果是大大的提高了CPU的利用率和计算机运行速度。</font></p>
<p><font face="楷体_GB2312">&#8230;&#8230;</font></p>
<p>这是一个典型计算机基础教材针对内存的描述，也许作为计算机专业的程序员对这段描述并不陌生。但也因为这段描述，而对内存的处理速度有神话的理解，认为内存中的处理速度是非常快的。</p>
<p>以使持有这种观点的程序员遇到一个巨型的内存查询循环的较长时间时，而束手无策了。</p>
<p><strong>请看一下如下程序：</strong></p>
<table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0">
    <tbody>
        <tr>
            <td bgcolor="#e6e6e6">
            <pre>public class MemFor{<br />
            <br />
            public static void main (String[] args) {<br />
            <br />
            long start=System.currentTimeMillis(); //取得当前时间<br />
            <br />
            int len=1024*1024*3;&nbsp;&nbsp; //设定循环次数<br />
            <br />
            int [][] abc=new int[len][2];<br />
            <br />
            for (int i=0;i&lt;len;i++){<br />
            <br />
            abc[i][0]=i;<br />
            <br />
            abc[i][1]=(i+1);<br />
            <br />
            }<br />
            <br />
            long get=System.currentTimeMillis();&nbsp; //取得当前时间<br />
            <br />
            //循环将想要的数值取出来，本程序取数组的最后一个值<br />
            <br />
            for (int i=0;i&lt;len;i++){<br />
            <br />
            if ((int)abc[i][0]==(1024*1024*3-1)){<br />
            <br />
            System.out.println("取值结果:"+abc[i][1]);<br />
            <br />
            }<br />
            <br />
            }<br />
            <br />
            long end=System.currentTimeMillis();&nbsp;&nbsp; //取得当前时间<br />
            <br />
            //输出测试结果<br />
            <br />
            System.out.println("赋值循环时间:"+(get-start)+"ms");<br />
            <br />
            System.out.println("获取循环时间:"+(end-get)+"ms");<br />
            <br />
            System.out.print("Java可控内存:");<br />
            <br />
            System.out.println(Runtime.getRuntime().maxMemory()/1024/1024+"M");<br />
            <br />
            System.out.print("已占用内存:");<br />
            <br />
            System.out.println(Runtime.getRuntime().totalMemory()/1024/1024+"M");<br />
            <br />
            }<br />
            <br />
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
运行这个程序：
<table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0">
    <tbody>
        <tr>
            <td bgcolor="#e6e6e6">
            <pre>java -Xmx1024m MemFor<br />
            <br />
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<p><strong>程序的运行结果如下：</strong></p>
<p>取值结果:3145728</p>
<p>赋值循环时间:2464ms</p>
<p>获取循环时间:70ms</p>
<p>Java可控内存:1016M</p>
<p>已占用内存:128M</p>
<p>我们发现，这个程序循环了3145728次获得想要的结果，循环获取数值的时间用了70毫秒。</p>
<p><font face="楷体_GB2312">你觉得快吗？</font></p>
<p><font face="楷体_GB2312">是啊，70毫秒虽然小于1秒钟，但是如果你不得不在这个循环外面再套一个循环，即使外层嵌套的循环只有100次，那么，想想看是多少毫秒呢？</font></p>
<p><font face="楷体_GB2312">回答：70毫秒*100=7000毫秒=7秒</font></p>
<p><font face="楷体_GB2312">如果，循环1000次呢？</font></p>
<p><font face="楷体_GB2312">70秒！</font></p>
<p><font face="楷体_GB2312">70秒的运行时间对于这个程序来说就是灾难了。<br />
</font>&nbsp;<br />
面对这个程序的运行时间很多程序员已经束手无策了，其实，Java给程序员们提供了一个较快的查询方法--哈希表查询。</p>
<p>我们将这个程序用"HashMap"来改造一下，再看看运行结果：</p>
<table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0">
    <tbody>
        <tr>
            <td bgcolor="#e6e6e6">
            <pre>import java.util.*;<br />
            <br />
            public class HashMapTest{<br />
            <br />
            public static void main (String[] args) {<br />
            <br />
            HashMap has=new HashMap();<br />
            <br />
            int len=1024*1024*3;<br />
            <br />
            long start=System.currentTimeMillis();<br />
            <br />
            for (int i=0;i&lt;len;i++){<br />
            <br />
            has.put(""+i,""+i);<br />
            <br />
            }<br />
            <br />
            long end=System.currentTimeMillis();<br />
            <br />
            System.out.println("取值结果:"+has.get(""+(1024*1024*3-1)));<br />
            <br />
            long end2=System.currentTimeMillis();<br />
            <br />
            System.out.println("赋值循环时间:"+(end-start)+"ms");<br />
            <br />
            System.out.println("获取循环时间:"+(end2-end)+"ms");<br />
            <br />
            System.out.print("Java可控内存:");<br />
            <br />
            System.out.println(Runtime.getRuntime().maxMemory()/1024/1024+"M");<br />
            <br />
            System.out.print("已占用内存:");<br />
            <br />
            System.out.println(Runtime.getRuntime().totalMemory()/1024/1024+"M");<br />
            <br />
            }<br />
            <br />
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
<strong>运行这个程序：</strong><br />
<table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0">
    <tbody>
        <tr>
            <td bgcolor="#e6e6e6">
            <pre>java -Xmx1024m HashMapTest</pre>
            </td>
        </tr>
    </tbody>
</table>
<p><strong>程序的运行结果如下：</strong></p>
<p>取之结果:3145727</p>
<p>赋值循环时间:16454ms</p>
<p>获取循环时间:0ms</p>
<p>Java可控内存:1016M</p>
<p>已占用内存:566M</p>
<p>那么现在用HashMap来取值的时间竟然不到1ms，这时我们的程序的效率明显提高了，看来用哈希表进行内存中的数据搜索速度确实很快。</p>
<p>在提高数据搜索速度的同时也要注意到，赋值时间的差异和内存占用的差异。</p>
<p><strong>赋值循环时间：</strong></p>
<p>HashMap：16454ms</p>
<p>普通数组：2464ms</p>
<p>占用内存：</p>
<p>HashMap：566M</p>
<p>普通数组：128M</p>
<p>因此，可以看出HashMap在初始化以及内存占用方面都要高于普通数组，如果仅仅是为了数据存储，用普通数组是比较适合的，但是，如果为了频繁查询的目的，HashMap是必然的选择。<br />
</p>
<p><strong>启示5：用"arrayCopy()"提高数组截取速度</strong></p>
<p>当我们需要处理一个大的数组应用时往往需要对数组进行大面积截取与复制操作，比如针对图形显示的应用时单纯的通过对数组元素的处理操作有时捉襟见肘。</p>
<p>提高数组处理速度的一个很好的方法是"System.arrayCopy()"，这个方法可以提高数组的截取速度，我们可以做一个对比试验。</p>
<p>例如我们用普通的数组赋值方法来处理程序如下：</p>
<table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0">
    <tbody>
        <tr>
            <td bgcolor="#e6e6e6">
            <pre>public class arraycopyTest1{<br />
            <br />
            public static void main( String[] args ){<br />
            <br />
            String temp="abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br />
            <br />
            +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br />
            <br />
            +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br />
            <br />
            +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br />
            <br />
            +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br />
            <br />
            +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br />
            <br />
            +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br />
            <br />
            +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br />
            <br />
            +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br />
            <br />
            +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";<br />
            <br />
            char[] oldArray=temp.toCharArray();<br />
            <br />
            char[] newArray=null;<br />
            <br />
            long start=0L;<br />
            <br />
            newArray=new char[length]; <br />
            <br />
            //开始时间记录<br />
            <br />
            start=System.currentTimeMillis();<br />
            <br />
            for(int i=0;i&lt;10000000;i++){<br />
            <br />
            for(int j=0;j&lt;length;j++){<br />
            <br />
            newArray[j]=oldArray[begin+j];<br />
            <br />
            }<br />
            <br />
            }<br />
            <br />
            //打印总用时间<br />
            <br />
            System.out.println(System.currentTimeMillis()-start+"ms");<br />
            <br />
            }<br />
            <br />
            }<br />
            <br />
            </pre>
            </td>
        </tr>
    </tbody>
</table>
程序运行结果如图 3 8所示。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img src="http://www.blogjava.net/images/blogjava_net/gen-sky/1126040.jpg" alt="" border="0" /><br />
<br />
那么下面我们再用arrayCopy()的方法试验一下：<br />
<table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0">
    <tbody>
        <tr>
            <td bgcolor="#e6e6e6">
            <pre>public final class arraycopyTest2{<br />
            <br />
            public static void main( String[] args ){<br />
            <br />
            String temp="abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br />
            <br />
            +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br />
            <br />
            +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br />
            <br />
            +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br />
            <br />
            +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br />
            <br />
            +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br />
            <br />
            +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br />
            <br />
            +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br />
            <br />
            +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br />
            <br />
            +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";<br />
            <br />
            char[] oldArray=temp.toCharArray(); <br />
            <br />
            char[] newArray=null; <br />
            <br />
            long start=0L; <br />
            <br />
            newArray=new char[length]; <br />
            <br />
            //记录开始时间<br />
            <br />
            start=System.currentTimeMillis(); <br />
            <br />
            for(int i=0;i&lt;10000000;i++ ){<br />
            <br />
            System.arraycopy(oldArray,100,newArray,0,120);<br />
            <br />
            }<br />
            <br />
            //打印总用时间<br />
            <br />
            System.out.println((System.currentTimeMillis()-start)+"ms");<br />
            <br />
            }<br />
            <br />
            }<br />
            <br />
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<p>程序运行结果如图 3 9所示。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img src="http://www.blogjava.net/images/blogjava_net/gen-sky/1126041.jpg" alt="" border="0" /><br />
</p>
<br />
<p>两个程序的差距再3秒多，如果处理更大批量的数组他们的差距还会更大，因此，可以在适当的情况下用这个方法来处理数组的问题。</p>
<p>有时候我们为了使用方便，可以在自己的tools包中重载一个arrayCopy方法，如下：</p>
<table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0">
    <tbody>
        <tr>
            <td bgcolor="#e6e6e6">
            <pre>&nbsp;public static Object[] arrayCopy(int pos,Object[] srcObj){<br />
            <br />
            return arrayCopy(pos,srcObj.length,srcObj);<br />
            <br />
            }<br />
            <br />
            public static Object[] arrayCopy(int pos,int dest,Object[] srcObject){<br />
            <br />
            Object[] rv=null;<br />
            <br />
            rv=new Object[dest-pos];<br />
            <br />
            System.arraycopy(srcObject,pos,rv,0,rv.length);<br />
            <br />
            return rv;<br />
            <br />
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<img src ="http://www.blogjava.net/gen-sky/aggbug/285791.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gen-sky/" target="_blank">星期五</a> 2009-07-07 13:19 <a href="http://www.blogjava.net/gen-sky/articles/285791.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java和内存有关系                -------------------  学习自《Java程序员 上班那点事儿》</title><link>http://www.blogjava.net/gen-sky/articles/285787.html</link><dc:creator>星期五</dc:creator><author>星期五</author><pubDate>Tue, 07 Jul 2009 04:38:00 GMT</pubDate><guid>http://www.blogjava.net/gen-sky/articles/285787.html</guid><wfw:comment>http://www.blogjava.net/gen-sky/comments/285787.html</wfw:comment><comments>http://www.blogjava.net/gen-sky/articles/285787.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gen-sky/comments/commentRss/285787.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gen-sky/services/trackbacks/285787.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 堆和栈&nbsp; 栈与堆都是Java用来在内存中存放数据的地方。&nbsp; A.堆--用new建立，垃圾自动回收负责回收&nbsp;&nbsp;&nbsp;&nbsp; 1、堆是一个"运行时"数据区，类实例化的对象就是从堆上去分配空间的；&nbsp;&nbsp;&nbsp;&nbsp; 2、在堆上分配空间是通过"new"等指令建立的；&nbsp;&nbsp;&nbsp;&n...&nbsp;&nbsp;<a href='http://www.blogjava.net/gen-sky/articles/285787.html'>阅读全文</a><img src ="http://www.blogjava.net/gen-sky/aggbug/285787.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gen-sky/" target="_blank">星期五</a> 2009-07-07 12:38 <a href="http://www.blogjava.net/gen-sky/articles/285787.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>