﻿<?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-Jiangshachina-随笔分类-OpenJDK</title><link>http://www.blogjava.net/jiangshachina/category/54943.html</link><description>同是Java爱好者，相逢何必曾相识！&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;a cup of Java, cheers!</description><language>zh-cn</language><lastBuildDate>Sun, 08 Nov 2015 04:23:30 GMT</lastBuildDate><pubDate>Sun, 08 Nov 2015 04:23:30 GMT</pubDate><ttl>60</ttl><item><title>Play OpenJDK: 允许你的包名以"java."开头(原)</title><link>http://www.blogjava.net/jiangshachina/archive/2015/11/01/428010.html</link><dc:creator>Sha Jiang</dc:creator><author>Sha Jiang</author><pubDate>Sun, 01 Nov 2015 12:06:00 GMT</pubDate><guid>http://www.blogjava.net/jiangshachina/archive/2015/11/01/428010.html</guid><wfw:comment>http://www.blogjava.net/jiangshachina/comments/428010.html</wfw:comment><comments>http://www.blogjava.net/jiangshachina/archive/2015/11/01/428010.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangshachina/comments/commentRss/428010.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangshachina/services/trackbacks/428010.html</trackback:ping><description><![CDATA[<div><div align="center"><strong><span style="font-size: 14pt;">Play OpenJDK: 允许你的包名以"java."开头</span></strong></div><br />本文是Play OpenJDK的第二篇，介绍了如何突破JDK不允许自定义的包名以"java."开头这一限制。这一技巧对于基于已有的JDK向java.*中添加新类还是有所帮助的。(2015.11.02最后更新)<br /><br />无论是经验丰富的Java程序员，还是Java的初学者，总会有一些人或有意或无意地创建一个包名为"java"的类。但出于安全方面的考虑，JDK不允许应用程序类的包名以"java"开头，即不允许java，java.foo这样的包名。但javax，javaex这样的包名是允许的。<br /><br /><strong><span style="font-size: 12pt;">1. 例子</span></strong><br />比如，以OpenJDK 8为基础，臆造这样一个例子。笔者想向OpenJDK贡献一个同步的HashMap，即类SynchronizedHashMap，而该类的包名就为java.util。SynchronizedHashMap是HashMap的同步代理，由于这两个类是在同一包内，SynchronizedHashMap不仅可以访问HashMap的public方法与变量，还可以访问HashMap的protected和default方法与变量。SynchronizedHashMap看起来可能像下面这样：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">package</span><span style="color: #000000; ">&nbsp;java.util;<br /><br /></span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;SynchronizedHashMap</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">K,&nbsp;V</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">&nbsp;HashMap</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">K,&nbsp;V</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;hashMap&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;SynchronizedHashMap(HashMap</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">K,&nbsp;V</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;hashMap)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">.hashMap&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;hashMap;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;SynchronizedHashMap()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">(</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;HashMap</span><span style="color: #000000; ">&lt;&gt;</span><span style="color: #000000; ">());<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">synchronized</span><span style="color: #000000; ">&nbsp;V&nbsp;put(K&nbsp;key,&nbsp;V&nbsp;value)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;hashMap.put(key,&nbsp;value);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">synchronized</span><span style="color: #000000; ">&nbsp;V&nbsp;get(K&nbsp;key)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;hashMap.get(key);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">synchronized</span><span style="color: #000000; ">&nbsp;V&nbsp;remove(K&nbsp;key)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;hashMap.remove(key);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">synchronized</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;size()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;hashMap.size;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;直接调用HashMap.size变量，而非HashMap.size()方法</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}<br />}</span></div><br /><strong><span style="font-size: 12pt;">2. ClassLoader的限制</span></strong><br />使用javac去编译源文件SynchronizedHashMap.java并没有问题，但在使用编译后的SynchronizedHashMap.class时，JDK的ClassLoader则会拒绝加载java.util.SynchronizedHashMap。<br />设想有如下的应用程序：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;java.util.SynchronizedHashMap;<br /><br /></span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;SyncMapTest&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">static</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;main(String[]&nbsp;args)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SynchronizedHashMap</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">String,&nbsp;String</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;syncMap&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;SynchronizedHashMap</span><span style="color: #000000; ">&lt;&gt;</span><span style="color: #000000; ">();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;syncMap.put(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Key</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Value</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(syncMap.get(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Key</span><span style="color: #000000; ">"</span><span style="color: #000000; ">));<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}</span></div>使用java命令去运行该应用时，会报如下错误：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">Exception&nbsp;in&nbsp;thread&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">main</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;java.lang.SecurityException:&nbsp;Prohibited&nbsp;package&nbsp;name:&nbsp;java.util<br />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.lang.ClassLoader.preDefineClass(ClassLoader.java:</span><span style="color: #000000; ">659</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.lang.ClassLoader.defineClass(ClassLoader.java:</span><span style="color: #000000; ">758</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.security.SecureClassLoader.defineClass(SecureClassLoader.java:</span><span style="color: #000000; ">142</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.net.URLClassLoader.defineClass(URLClassLoader.java:</span><span style="color: #000000; ">467</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.net.URLClassLoader.access$</span><span style="color: #000000; ">100</span><span style="color: #000000; ">(URLClassLoader.java:</span><span style="color: #000000; ">73</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.net.URLClassLoader$</span><span style="color: #000000; ">1</span><span style="color: #000000; ">.run(URLClassLoader.java:</span><span style="color: #000000; ">368</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.net.URLClassLoader$</span><span style="color: #000000; ">1</span><span style="color: #000000; ">.run(URLClassLoader.java:</span><span style="color: #000000; ">362</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.security.AccessController.doPrivileged(Native&nbsp;Method)<br />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.net.URLClassLoader.findClass(URLClassLoader.java:</span><span style="color: #000000; ">361</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.lang.ClassLoader.loadClass(ClassLoader.java:</span><span style="color: #000000; ">424</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:</span><span style="color: #000000; ">331</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.lang.ClassLoader.loadClass(ClassLoader.java:</span><span style="color: #000000; ">357</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;SyncMapTest.main(SyncMapTest.java:</span><span style="color: #000000; ">6</span><span style="color: #000000; ">)</span></div>方法ClassLoader.preDefineClass()的源代码如下：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">private</span><span style="color: #000000; ">&nbsp;ProtectionDomain&nbsp;preDefineClass(String&nbsp;name,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ProtectionDomain&nbsp;pd)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #000000; ">!</span><span style="color: #000000; ">checkName(name))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">throw</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;NoClassDefFoundError(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">IllegalName:&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;name);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;((name&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">)&nbsp;</span><span style="color: #000000; ">&amp;&amp;</span><span style="color: #000000; ">&nbsp;name.startsWith(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">java.</span><span style="color: #000000; ">"</span><span style="color: #000000; ">))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">throw</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;SecurityException<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Prohibited&nbsp;package&nbsp;name:&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;name.substring(</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,&nbsp;name.lastIndexOf(</span><span style="color: #000000; ">'</span><span style="color: #000000; ">.</span><span style="color: #000000; ">'</span><span style="color: #000000; ">)));<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(pd&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pd&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;defaultDomain;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(name&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">)&nbsp;checkCerts(name,&nbsp;pd.getCodeSource());<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;pd;<br />}</span></div>很清楚地，该方法会先检查待加载的类全名(即包名+类名)是否以"java."开头，如是，则抛出SecurityException。那么可以尝试修改该方法的源代码，以突破这一限制。<br />从JDK中的src.zip中拿出java/lang/ClassLoader.java文件，修改其中的preDefineClass方法以去除相关限制。重新编译ClassLoader.java，将生成的ClassLoader.class，ClassLoader$1.class，ClassLoader$2.class，ClassLoader$3.class，ClassLoader$NativeLibrary.class，ClassLoader$ParallelLoaders.class和SystemClassLoaderAction.class去替换JDK/jre/lib/rt.jar中对应的类。<br />再次运行SyncMapTest，却仍然会抛出相同的SecurityException，如下所示：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">Exception&nbsp;in&nbsp;thread&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">main</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;java.lang.SecurityException:&nbsp;Prohibited&nbsp;package&nbsp;name:&nbsp;java.util<br />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.lang.ClassLoader.defineClass1(Native&nbsp;Method)<br />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.lang.ClassLoader.defineClass(ClassLoader.java:</span><span style="color: #000000; ">760</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.security.SecureClassLoader.defineClass(SecureClassLoader.java:</span><span style="color: #000000; ">142</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.net.URLClassLoader.defineClass(URLClassLoader.java:</span><span style="color: #000000; ">467</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.net.URLClassLoader.access$</span><span style="color: #000000; ">100</span><span style="color: #000000; ">(URLClassLoader.java:</span><span style="color: #000000; ">73</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.net.URLClassLoader$</span><span style="color: #000000; ">1</span><span style="color: #000000; ">.run(URLClassLoader.java:</span><span style="color: #000000; ">368</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.net.URLClassLoader$</span><span style="color: #000000; ">1</span><span style="color: #000000; ">.run(URLClassLoader.java:</span><span style="color: #000000; ">362</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.security.AccessController.doPrivileged(Native&nbsp;Method)<br />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.net.URLClassLoader.findClass(URLClassLoader.java:</span><span style="color: #000000; ">361</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.lang.ClassLoader.loadClass(ClassLoader.java:</span><span style="color: #000000; ">424</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:</span><span style="color: #000000; ">331</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.lang.ClassLoader.loadClass(ClassLoader.java:</span><span style="color: #000000; ">357</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;SyncMapTest.main(SyncMapTest.java:</span><span style="color: #000000; ">6</span><span style="color: #000000; ">)</span></div>此时是由方法ClassLoader.defineClass1()抛出的SecurityException。但这是一个native方法，那么仅通过修改Java代码是无法解决这个问题的(JDK真是层层设防啊)。原来在Hotspot的C++源文件hotspot/src/share/vm/classfile/systemDictionary.cpp中有如下语句：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">const&nbsp;char*&nbsp;pkg&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">java/</span><span style="color: #000000; ">"</span><span style="color: #008000; ">;<br /></span><span style="color: #000000; ">if&nbsp;(!HAS_PENDING_EXCEPTION&nbsp;&amp;&amp;<br />&nbsp;&nbsp;&nbsp;&nbsp;!class_loader.is_null()&nbsp;&amp;&amp;<br />&nbsp;&nbsp;&nbsp;&nbsp;parsed_name&nbsp;!</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;NULL&nbsp;&amp;&amp;<br />&nbsp;&nbsp;&nbsp;&nbsp;!strncmp((const&nbsp;char*)parsed_name-&gt;bytes()</span><span style="color: #000000; ">,</span><span style="color: #000000; ">&nbsp;pkg</span><span style="color: #000000; ">,</span><span style="color: #000000; ">&nbsp;strlen(pkg)))&nbsp;{<br />&nbsp;&nbsp;//&nbsp;It&nbsp;is&nbsp;illegal&nbsp;to&nbsp;define&nbsp;classes&nbsp;in&nbsp;the&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">java.</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;package&nbsp;from<br />&nbsp;&nbsp;//&nbsp;JVM_DefineClass&nbsp;or&nbsp;jni_DefineClass&nbsp;unless&nbsp;you're&nbsp;the&nbsp;bootclassloader<br />&nbsp;&nbsp;ResourceMark&nbsp;rm(THREAD)</span><span style="color: #008000; ">;<br /></span><span style="color: #000000; ">&nbsp;&nbsp;char*&nbsp;name&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;parsed_name-&gt;as_C_string()</span><span style="color: #008000; ">;<br /></span><span style="color: #000000; ">&nbsp;&nbsp;char*&nbsp;index&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;strrchr(name</span><span style="color: #000000; ">,</span><span style="color: #000000; ">&nbsp;'/')</span><span style="color: #008000; ">;<br /></span><span style="color: #000000; ">&nbsp;&nbsp;*index&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;'\</span><span style="color: #000000; ">0</span><span style="color: #000000; ">'</span><span style="color: #008000; ">;</span><span style="color: #008000; ">&nbsp;//&nbsp;chop&nbsp;to&nbsp;just&nbsp;the&nbsp;package&nbsp;name</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;while&nbsp;((index&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;strchr(name</span><span style="color: #000000; ">,</span><span style="color: #000000; ">&nbsp;'/'))&nbsp;!</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;NULL)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;*index&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;'.'</span><span style="color: #008000; ">;</span><span style="color: #008000; ">&nbsp;//&nbsp;replace&nbsp;'/'&nbsp;with&nbsp;'.'&nbsp;in&nbsp;package&nbsp;name</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;}<br />&nbsp;&nbsp;const&nbsp;char*&nbsp;fmt&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Prohibited&nbsp;package&nbsp;name:&nbsp;%s</span><span style="color: #000000; ">"</span><span style="color: #008000; ">;<br /></span><span style="color: #000000; ">&nbsp;&nbsp;size_t&nbsp;len&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;strlen(fmt)&nbsp;+&nbsp;strlen(name)</span><span style="color: #008000; ">;<br /></span><span style="color: #000000; ">&nbsp;&nbsp;char*&nbsp;message&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;NEW_RESOURCE_ARRAY(char</span><span style="color: #000000; ">,</span><span style="color: #000000; ">&nbsp;len)</span><span style="color: #008000; ">;<br /></span><span style="color: #000000; ">&nbsp;&nbsp;jio_snprintf(message</span><span style="color: #000000; ">,</span><span style="color: #000000; ">&nbsp;len</span><span style="color: #000000; ">,</span><span style="color: #000000; ">&nbsp;fmt</span><span style="color: #000000; ">,</span><span style="color: #000000; ">&nbsp;name)</span><span style="color: #008000; ">;<br /></span><span style="color: #000000; ">&nbsp;&nbsp;Exceptions::_throw_msg(THREAD_AND_LOCATION</span><span style="color: #000000; ">,</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;vmSymbols::java_lang_SecurityException()</span><span style="color: #000000; ">,</span><span style="color: #000000; ">&nbsp;message)</span><span style="color: #008000; ">;<br /></span><span style="color: #000000; ">}</span></div>修改该文件以去除掉相关限制，并按照本系列的<a href="http://www.blogjava.net/jiangshachina/archive/2015/10/30/427994.html">第一篇文章</a>中介绍的方法去重新构建一个OpenJDK。那么，这个新的JDK将不会再对包名有任何限制了。<br /><br /><div><strong style="font-size: 12pt;">3. 覆盖Java核心API？</strong><br />开发者们在使用主流IDE时会发现，如果工程有多个jar文件或源文件目录中包含相同的类，这些IDE会根据用户指定的优先级顺序来加载这些类。比如，在Eclipse中，右键点击某个Java工程--&gt;属性--&gt;Java Build Path--&gt;Order and Export，在这里调整各个类库或源文件目录的位置，即可指定加载类的优先级。<br />当开发者在使用某个开源类库(jar文件)时，想对其中某个类进行修改，那么就可以将该类的源代码复制出来，并在Java工程中创建一个同名类，然后指定Eclipse优先加息自己创建的类。即，在编译时与运行时用自己创建的类去覆盖类库中的同名类。那么，是否可以如法炮制去覆盖Java核心API中的类呢？<br />考虑去覆盖类java.util.HashMap，只是简单在它的put()方法添加一条打印语。那么就需要将src.zip中的java/util/HashMap.java复制出来，并在当前Java工程中创建一个同名类java.util.HashMap，并修改put()方法，如下所示：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">package</span><span style="color: #000000; ">&nbsp;java.util;<br /><br /></span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;HashMap</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">K,V</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">extends</span><span style="color: #000000; ">&nbsp;AbstractMap</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">K,V</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">implements</span><span style="color: #000000; ">&nbsp;Map</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">K,V</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">,&nbsp;Cloneable,&nbsp;Serializable&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" />.<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;V&nbsp;put(K&nbsp;key,&nbsp;V&nbsp;value)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.printf(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">put&nbsp;-&nbsp;key=%s,&nbsp;value=%s%n</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;key,&nbsp;value);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;putVal(hash(key),&nbsp;key,&nbsp;value,&nbsp;</span><span style="color: #0000FF; ">false</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" /><br />}</span></div>此时，在Eclipse环境中，SynchronizedHashMap使用的java.util.HashMap被认为是上述新创建的HashMap类。那么运行应用程序SyncMapTest后的期望输出应该如下所示：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">put&nbsp;-&nbsp;key</span><span style="color: #000000; ">=</span><span style="color: #000000; ">Key</span><span style="color: #000000; ">,</span><span style="color: #000000; ">&nbsp;value</span><span style="color: #000000; ">=</span><span style="color: #000000; ">Value<br />Value</span></div>但运行SyncMapTest后的实际输出却为如下：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">Value</span></div>看起来，新创建的java.util.HashMap并没有被使用上。这是为什么呢？能够"想像"到的原因还是类加载器。关于Java类加载器的讨论超出了本文的范围，而且关于该主题的文章已是汗牛充栋，但本文仍会简述其要点。<br />Java类加载器由下至上分为三个层次：引导类加载器(Bootstrap Class Loader)，扩展类加载器(Extension Class Loader)和应用程序类加载器(Application Class Loader)。其中引导类加载器用于加载rt.jar这样的核心类库。并且引导类加载器为扩展类加载器的父加载器，而扩展类加载器又为应用程序类加载器的父加载器。同时JVM在加载类时实行委托模式。即，当前类加载器在加载类时，会首先委托自己的父加载器去进行加载。如果父加载器已经加载了某个类，那么子加载器将不会再次加载。<br />由上可知，当应用程序试图加载java.util.Map时，它会首先逐级向上委托父加载器去加载该类，直到引导类加载器加载到rt.jar中的java.util.HashMap。由于该类已经被加载了，我们自己创建的java.util.HashMap就不会被重复加载。<br />使用java命令运行SyncMapTest程序时加上VM参数-verbose:class，会在窗口中打印出形式如下的语句：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #800000; font-weight: bold; ">[</span><span style="color: #800000; ">Opened&nbsp;/home/ubuntu/jdk1.8.0_custom/jre/lib/rt.jar</span><span style="color: #800000; font-weight: bold; ">]</span><span style="color: #000000; "><br /></span><span style="color: #800000; font-weight: bold; ">[</span><span style="color: #800000; ">Loaded&nbsp;java.lang.Object&nbsp;from&nbsp;/home/ubuntu/jdk1.8.0_custom/jre/lib/rt.jar</span><span style="color: #800000; font-weight: bold; ">]</span><span style="color: #000000; "><br /><img src="http://www.blogjava.net/Images/dot.gif" alt="" /><br /></span><span style="color: #800000; font-weight: bold; ">[</span><span style="color: #800000; ">Loaded&nbsp;java.util.HashMap&nbsp;from&nbsp;/home/ubuntu/jdk1.8.0_custom/jre/lib/rt.jar</span><span style="color: #800000; font-weight: bold; ">]</span><span style="color: #000000; "><br /></span><span style="color: #800000; font-weight: bold; ">[</span><span style="color: #800000; ">Loaded&nbsp;java.util.HashMap$Node&nbsp;from&nbsp;/home/ubuntu/jdk1.8.0_custom/jre/lib/rt.jar</span><span style="color: #800000; font-weight: bold; ">]</span><span style="color: #000000; "><br /><img src="http://www.blogjava.net/Images/dot.gif" alt="" /><br /></span><span style="color: #800000; font-weight: bold; ">[</span><span style="color: #800000; ">Loaded&nbsp;java.util.SynchronizedHashMap&nbsp;from&nbsp;file:/home/ubuntu/projects/test/classes/</span><span style="color: #800000; font-weight: bold; ">]</span><span style="color: #000000; "><br />Value<br /></span><span style="color: #800000; font-weight: bold; ">[</span><span style="color: #800000; ">Loaded&nbsp;java.lang.Shutdown&nbsp;from&nbsp;/home/ubuntu/jdk1.8.0_custom/jre/lib/rt.jar</span><span style="color: #800000; font-weight: bold; ">]</span><span style="color: #000000; "><br /></span><span style="color: #800000; font-weight: bold; ">[</span><span style="color: #800000; ">Loaded&nbsp;java.lang.Shutdown$Lock&nbsp;from&nbsp;/home/ubuntu/jdk1.8.0_custom/jre/lib/rt.jar</span><span style="color: #800000; font-weight: bold; ">]</span></div>从中可以看出，类java.util.HashMap确实是从rt.jar中加载到的。但理论上，可以通过自定义类加载器去打破委托模式，然而这就是另一个话题了。</div></div><img src ="http://www.blogjava.net/jiangshachina/aggbug/428010.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangshachina/" target="_blank">Sha Jiang</a> 2015-11-01 20:06 <a href="http://www.blogjava.net/jiangshachina/archive/2015/11/01/428010.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Play OpenJDK: 构建你自己的JDK(原)</title><link>http://www.blogjava.net/jiangshachina/archive/2015/10/30/427994.html</link><dc:creator>Sha Jiang</dc:creator><author>Sha Jiang</author><pubDate>Fri, 30 Oct 2015 15:17:00 GMT</pubDate><guid>http://www.blogjava.net/jiangshachina/archive/2015/10/30/427994.html</guid><wfw:comment>http://www.blogjava.net/jiangshachina/comments/427994.html</wfw:comment><comments>http://www.blogjava.net/jiangshachina/archive/2015/10/30/427994.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangshachina/comments/commentRss/427994.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangshachina/services/trackbacks/427994.html</trackback:ping><description><![CDATA[<div><div align="center"><strong style="font-size: 14pt;"><span style="font-size: 14pt;">Play OpenJDK: 构建你自己的JDK</span></strong></div><br />计划使Play OpenJDK成为一组介绍如何使用并参与OpenJDK项目的系列文章。本文是该系列的第一篇文章，它基于OpenJDK 8的源代码介绍了构建一个属于自己的JDK方法。(2015.10.30最后更新)<br /><br /><strong><span style="font-size: 12pt;">1. OpenJDK</span></strong><br />曾经的Sun Microsystems. Inc，也就是Java语言的发明者，将它的JDK代码贡献出来，成立了一个开源项目，即<a href="http://openjdk.java.net/">OpenJDK</a>。<br />&nbsp;&nbsp;&nbsp; 同时，它也是一个社区。相关的公司，组织和个人在这个社区中协作开发OpenJDK。社区根据不同的领域或项目提供了一系列的<a href="http://mail.openjdk.java.net/mailman/listinfo">邮件列表</a>，利益相关方或对其感兴趣的个人都可以订阅这些邮件列表去进行关注和讨论。例如，Java核心API的邮件列表是core-libs-dev@openjdk.java.net，关于java.lang，java.util等核心API的新特性都会在这里进行讨论，并对其最终的实现代码进行审查。任何将要进入OpenJDK版本库的源代码，无论是产品代码(即，要随JDK发布的程序)，还是测试代码，都需要在社区中进行公开的代码审查。<br />&nbsp;&nbsp;&nbsp; 选择一个自己感兴趣的领域或项目，加入它的邮件列表，长期跟踪它的发展，看着专家们的讨论、争论推动JDK的演进，学习开发者们的API设计与代码实现，...，这些对自己的成长都是极有帮助的。也许，还能看到一些有趣的八卦;-)<br /><br /><strong><span style="font-size: 12pt;">2. 准备工作</span></strong><br />在几种主流操作系统，Linux(如Ubuntu和Fedora)，Windows(7和8)，MacOS(Lion和Moutain Lion)，中都可以构建OpenJDK，具体的细节可以参见<a href="https://java.net/projects/adoptopenjdk/pages/AdoptOpenJDKBuildInstructions">官方的一篇文档</a>。<br />&nbsp;&nbsp;&nbsp; 本文选择使用Ubuntu 14.04。坦白地说，选择使用Ubuntu，实是因为在Linux环境中构建OpenJDK非常简单。若在Windows中进行构建，则需要安装Visual Studio C++编译器。MacOS？嗯，我没有MBP。可能更多人平时是使用Windows，但安装一个Linux也不麻烦。先安装免费的VM工具<a href="https://www.virtualbox.org/">VirtaulBox</a>，再去下载Ubuntu的<a href="http://www.ubuntu.com/download/server">ISO文件</a>，然后使用VirtualBox去安装Ubuntu。VirtualBox简单易用，网上的相关资料也非常的多。<br />&nbsp;&nbsp;&nbsp; OpenJDK的源文件版本库基于<a href="https://www.mercurial-scm.org/">Mercurial</a>(hg)，它是一个与Git相似的分布式版本控制工具。在Ubuntu中安装Mercurial只需要执行命令<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">$ sudo&nbsp;apt</span><span style="color: #000000; ">-</span><span style="color: #000000; ">get&nbsp;install&nbsp;mercurial</span></div>&nbsp;&nbsp;&nbsp; OpenJDK中各项目的源代码版本库的路径均在http://hg.openjdk.java.net/之下，在这里可以找到6，7，8，9和Jigsaw的源代码。其中JDK 8的最新开发版本库路径为http://hg.openjdk.java.net/jdk8u/jdk8u-dev/。<br />&nbsp;&nbsp;&nbsp; 另外，构建OpenJDK时需要一个启动JDK，本文选择构建OpenJDK 8，那么启动JDK的版本应不低于7。<br /><br /><strong><span style="font-size: 12pt;">3. 下载源代码</span></strong><br />克隆版本库，<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">$&nbsp;hg&nbsp;clone&nbsp;http</span><span style="color: #000000; ">://</span><span style="color: #000000; ">hg</span><span style="color: #000000; ">.</span><span style="color: #000000; ">openjdk</span><span style="color: #000000; ">.</span><span style="color: #000000; ">java</span><span style="color: #000000; ">.</span><span style="color: #000000; ">net</span><span style="color: #000000; ">/</span><span style="color: #000000; ">jdk8u</span><span style="color: #000000; ">/</span><span style="color: #000000; ">jdk8u</span><span style="color: #000000; ">-</span><span style="color: #000000; ">dev</span><span style="color: #000000; ">/</span><span style="color: #000000; ">&nbsp;jdk8</span><span style="color: #000000; ">-</span><span style="color: #000000; ">src<br />requesting&nbsp;all&nbsp;changes<br />adding&nbsp;changesets<br />adding&nbsp;manifests<br />adding&nbsp;file&nbsp;changes<br />added&nbsp;</span><span style="color: #800000; ">1570</span><span style="color: #000000; ">&nbsp;changesets&nbsp;with&nbsp;</span><span style="color: #800000; ">1958</span><span style="color: #000000; ">&nbsp;changes&nbsp;to&nbsp;</span><span style="color: #800000; ">141</span><span style="color: #000000; ">&nbsp;files<br />updating&nbsp;to&nbsp;branch&nbsp;default<br /></span><span style="color: #800000; ">85</span><span style="color: #000000; ">&nbsp;files&nbsp;updated</span><span style="color: #000000; ">,</span><span style="color: #000000; ">&nbsp;</span><span style="color: #800000; ">0</span><span style="color: #000000; ">&nbsp;files&nbsp;merged</span><span style="color: #000000; ">,</span><span style="color: #000000; ">&nbsp;</span><span style="color: #800000; ">0</span><span style="color: #000000; ">&nbsp;files&nbsp;removed</span><span style="color: #000000; ">,</span><span style="color: #000000; ">&nbsp;</span><span style="color: #800000; ">0</span><span style="color: #000000; ">&nbsp;files&nbsp;unresolved</span></div>进入源代码目录<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">$&nbsp;cd&nbsp;jdk8</span><span style="color: #000000; ">-</span><span style="color: #000000; ">src</span><span style="color: #000000; ">/</span></div>OpenJDK的源代码版本库实际上包含多个独立的子版本库，需要执行如下脚本去分别下载各个子版本库的源代码，<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">$&nbsp;sh&nbsp;get_source</span><span style="color: #000000; ">.</span><span style="color: #000000; ">sh<br /></span><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;Repositories:&nbsp;&nbsp;corba&nbsp;jaxp&nbsp;jaxws&nbsp;langtools&nbsp;jdk&nbsp;hotspot&nbsp;nashorn</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;corba</span><span style="color: #000000; ">:</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;hg&nbsp;clone&nbsp;http</span><span style="color: #000000; ">://</span><span style="color: #000000; ">hg</span><span style="color: #000000; ">.</span><span style="color: #000000; ">openjdk</span><span style="color: #000000; ">.</span><span style="color: #000000; ">java</span><span style="color: #000000; ">.</span><span style="color: #000000; ">net</span><span style="color: #000000; ">/</span><span style="color: #000000; ">jdk8u</span><span style="color: #000000; ">/</span><span style="color: #000000; ">jdk8u</span><span style="color: #000000; ">-</span><span style="color: #000000; ">dev</span><span style="color: #000000; ">/</span><span style="color: #000000; ">corba&nbsp;corba<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jaxp</span><span style="color: #000000; ">:</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;hg&nbsp;clone&nbsp;http</span><span style="color: #000000; ">://</span><span style="color: #000000; ">hg</span><span style="color: #000000; ">.</span><span style="color: #000000; ">openjdk</span><span style="color: #000000; ">.</span><span style="color: #000000; ">java</span><span style="color: #000000; ">.</span><span style="color: #000000; ">net</span><span style="color: #000000; ">/</span><span style="color: #000000; ">jdk8u</span><span style="color: #000000; ">/</span><span style="color: #000000; ">jdk8u</span><span style="color: #000000; ">-</span><span style="color: #000000; ">dev</span><span style="color: #000000; ">/</span><span style="color: #000000; ">jaxp&nbsp;jaxp<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;corba</span><span style="color: #000000; ">:</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;requesting&nbsp;all&nbsp;changes<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jaxp</span><span style="color: #000000; ">:</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;requesting&nbsp;all&nbsp;changes<br /></span><span style="color: #000000; "><img src="http://www.blogjava.net/Images/dot.gif" alt="" /></span></div><br /><strong><span style="font-size: 12pt;">4. 构建</span></strong><br />调用configure进行预构建，其中的参数--with-boot-jdk用于指定启动JDK的路径。如果启动JDK的java命令已存在于PATH环境变量中，该参数可以忽略。<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">$ sh&nbsp;configure&nbsp;</span><span style="color: #000000; ">--</span><span style="color: #000000; ">with</span><span style="color: #000000; ">-</span><span style="color: #000000; ">boot</span><span style="color: #000000; ">-</span><span style="color: #000000; ">jdk</span><span style="color: #000000; ">=<em>/</em></span><em><span style="color: #000000; ">path</span><span style="color: #000000; ">/</span><span style="color: #000000; ">to</span><span style="color: #000000; ">/</span><span style="color: #000000; ">boot</span><span style="color: #000000; ">/</span><span style="color: #000000; ">jdk</span></em></div>该过程会检测构建环境是否符合要求，如有问题，它会给出提示。比如，<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">configure</span><span style="color: #000000; ">:</span><span style="color: #000000; ">&nbsp;error</span><span style="color: #000000; ">:</span><span style="color: #000000; ">&nbsp;Could&nbsp;not&nbsp;find&nbsp;X11&nbsp;libraries</span><span style="color: #000000; ">.</span><span style="color: #000000; ">&nbsp;You&nbsp;might&nbsp;be&nbsp;able&nbsp;to&nbsp;fix&nbsp;this&nbsp;by&nbsp;running&nbsp;</span><span style="color: #000000; font-weight: bold; ">'</span><span style="color: #000000; font-weight: bold; ">sudo&nbsp;apt-get&nbsp;install&nbsp;libX11-dev&nbsp;libxext-dev&nbsp;libxrender-dev&nbsp;libxtst-dev&nbsp;libxt-dev</span><span style="color: #000000; font-weight: bold; ">'</span><span style="color: #000000; ">.</span></div>此时根据提示安装所需要的库即可。再重新执行上述configure命令，可能还会提示缺少其它的库，那么再次根据提示进行安装。如此反复，只到预构建成功完成。<br />最后就是进行构建，直接执行如下命令，<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">$ make&nbsp;all</span></div>在此过程中可以会遇到一些警告，不必理会，耐心等待...完成后，会出现如下的汇总信息，<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; "></span><div>----- Build times -------<br />Start 2015-10-30 22:11:10<br />End&nbsp;&nbsp; 2015-10-30 22:52:54<br />00:01:01 corba<br />00:01:08 demos<br />00:06:49 docs<br />00:19:37 hotspot<br />00:01:47 images<br />00:00:35 jaxp<br />00:00:49 jaxws<br />00:08:23 jdk<br />00:01:09 langtools<br />00:00:25 nashorn<br />00:41:44 TOTAL<br />-------------------------<br />Finished building OpenJDK for target 'all'<br /><span style="color: #000000;"></span></div></div>在当前路径下会生成一个build目录，构建好的JDK就在那里面。新JDK的具体路径类似于build/linux-x86_64-normal-server-release/images/jdk。可以执行如下命令去测试这个JDK，<br /><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; "></span><div>$ build/linux-x86_64-normal-server-release/images/jdk/bin/java -version<br />openjdk version "1.8.0-internal"<br />OpenJDK Runtime Environment (build 1.8.0-internal-ubuntu_2015_10_30_22_07-b00)<br />OpenJDK 64-Bit Server VM (build 25.66-b00, mixed mode)<br /><span style="color: #000000; "></span></div></div></div><img src ="http://www.blogjava.net/jiangshachina/aggbug/427994.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangshachina/" target="_blank">Sha Jiang</a> 2015-10-30 23:17 <a href="http://www.blogjava.net/jiangshachina/archive/2015/10/30/427994.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>