??xml version="1.0" encoding="utf-8" standalone="yes"?>69av视频在线播放,国产成人精品日本亚洲11,国产乱视频在线观看http://www.aygfsteel.com/jiangshachina/category/54943.html同是Java爱好者,盔R何必曾相识Q?lt;br>    a cup of Java, cheers!zh-cnSun, 08 Nov 2015 04:23:30 GMTSun, 08 Nov 2015 04:23:30 GMT60Play OpenJDK: 允许你的包名?java."开??http://www.aygfsteel.com/jiangshachina/archive/2015/11/01/428010.htmlSha JiangSha JiangSun, 01 Nov 2015 12:06:00 GMThttp://www.aygfsteel.com/jiangshachina/archive/2015/11/01/428010.htmlhttp://www.aygfsteel.com/jiangshachina/comments/428010.htmlhttp://www.aygfsteel.com/jiangshachina/archive/2015/11/01/428010.html#Feedback0http://www.aygfsteel.com/jiangshachina/comments/commentRss/428010.htmlhttp://www.aygfsteel.com/jiangshachina/services/trackbacks/428010.html
Play OpenJDK: 允许你的包名?java."开?/span>

本文是Play OpenJDK的第二篇Q介l了(jin)如何H破JDK不允许自定义的包名以"java."开头这一限制。这一技巧对于基于已有的JDK向java.*中添加新c还是有所帮助的?2015.11.02最后更?

无论是经验丰富的JavaE序员,q是Java的初学者,M(x)有一些h或有意或无意地创Z个包名ؓ(f)"java"的类。但Z安全斚w的考虑QJDK不允许应用程序类的包名以"java"开_(d)即不允许javaQjava.fooq样的包名。但javaxQjavaexq样的包名是允许的?br />
1. 例子
比如Q以OpenJDK 8为基Q臆造这样一个例子。笔者想向OpenJDK贡献一个同步的HashMapQ即cSynchronizedHashMapQ而该cȝ包名׃ؓ(f)java.util。SynchronizedHashMap是HashMap的同步代理,׃q两个类是在同一包内QSynchronizedHashMap不仅可以讉KHashMap的publicҎ(gu)与变量,q可以访问HashMap的protected和defaultҎ(gu)与变量。SynchronizedHashMap看v来可能像下面q样Q?br />
package java.util;

public class SynchronizedHashMap<K, V> {

    
private HashMap<K, V> hashMap = null;

    
public SynchronizedHashMap(HashMap<K, V> hashMap) {
        
this.hashMap = hashMap;
    }

    
public SynchronizedHashMap() {
        
this(new HashMap<>());
    }

    
public synchronized V put(K key, V value) {
        
return hashMap.put(key, value);
    }

    
public synchronized V get(K key) {
        
return hashMap.get(key);
    }

    
public synchronized V remove(K key) {
        
return hashMap.remove(key);
    }

    
public synchronized int size() {
        
return hashMap.size; // 直接调用HashMap.size变量Q而非HashMap.size()Ҏ(gu)
    }
}

2. ClassLoader的限?/span>
使用javacȝ译源文gSynchronizedHashMap.javaq没有问题,但在使用~译后的SynchronizedHashMap.classӞJDK的ClassLoader则会(x)拒绝加蝲java.util.SynchronizedHashMap?br />设想有如下的应用E序Q?br />
import java.util.SynchronizedHashMap;

public class SyncMapTest {

    
public static void main(String[] args) {
        SynchronizedHashMap
<String, String> syncMap = new SynchronizedHashMap<>();
        syncMap.put(
"Key""Value");
        System.out.println(syncMap.get(
"Key"));
    }
}
使用java命o(h)去运行该应用Ӟ?x)报如下错误Q?br />
Exception in thread "main" java.lang.SecurityException: Prohibited package name: java.util
    at java.lang.ClassLoader.preDefineClass(ClassLoader.java:
659)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:
758)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:
142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:
467)
    at java.net.URLClassLoader.access$
100(URLClassLoader.java:73)
    at java.net.URLClassLoader$
1.run(URLClassLoader.java:368)
    at java.net.URLClassLoader$
1.run(URLClassLoader.java:362)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:
361)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:
424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:
331)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:
357)
    at SyncMapTest.main(SyncMapTest.java:
6)
Ҏ(gu)ClassLoader.preDefineClass()的源代码如下Q?br />
private ProtectionDomain preDefineClass(String name,
        ProtectionDomain pd)
{
    
if (!checkName(name))
        
throw new NoClassDefFoundError("IllegalName: " + name);

    
if ((name != null&& name.startsWith("java.")) {
        
throw new SecurityException
            (
"Prohibited package name: " +
            name.substring(
0, name.lastIndexOf('.')));
    }
    
if (pd == null) {
        pd 
= defaultDomain;
        }

    
if (name != null) checkCerts(name, pd.getCodeSource());

    
return pd;
}
很清楚地Q该Ҏ(gu)?x)先(g)查待加蝲的类全名(卛_?cd)是否?java."开_(d)如是Q则抛出SecurityException。那么可以尝试修改该Ҏ(gu)的源代码Q以H破q一限制?br />从JDK中的src.zip中拿出java/lang/ClassLoader.java文gQ修改其中的preDefineClassҎ(gu)以去除相关限制。重新编译ClassLoader.javaQ将生成的ClassLoader.classQClassLoader$1.classQClassLoader$2.classQClassLoader$3.classQClassLoader$NativeLibrary.classQClassLoader$ParallelLoaders.class和SystemClassLoaderAction.classL换JDK/jre/lib/rt.jar中对应的cR?br />再次q行SyncMapTestQ却仍然?x)抛出相同的SecurityExceptionQ如下所C:(x)
Exception in thread "main" java.lang.SecurityException: Prohibited package name: java.util
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:
760)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:
142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:
467)
    at java.net.URLClassLoader.access$
100(URLClassLoader.java:73)
    at java.net.URLClassLoader$
1.run(URLClassLoader.java:368)
    at java.net.URLClassLoader$
1.run(URLClassLoader.java:362)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:
361)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:
424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:
331)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:
357)
    at SyncMapTest.main(SyncMapTest.java:
6)
此时是由Ҏ(gu)ClassLoader.defineClass1()抛出的SecurityException。但q是一个nativeҎ(gu)Q那么仅通过修改Java代码是无法解册个问题的(JDK真是层层N?。原来在Hotspot的C++源文件hotspot/src/share/vm/classfile/systemDictionary.cpp中有如下语句Q?br />
const char* pkg = "java/";
if (!HAS_PENDING_EXCEPTION &&
    !class_loader.is_null() &&
    parsed_name !
= NULL &&
    !strncmp((const char*)parsed_name->bytes()
, pkg, strlen(pkg))) {
  // It is illegal to define classes in the 
"java." package from
  // JVM_DefineClass or jni_DefineClass unless you're the bootclassloader
  ResourceMark rm(THREAD)
;
  char* name = parsed_name->as_C_string();
  char* index = strrchr(name, '/');
  *index = '\0'; // chop to just the package name
  while ((index = strchr(name, '/')) != NULL) {
    *index 
= '.'; // replace '/' with '.' in package name
  }
  const char* fmt 
= "Prohibited package name: %s";
  size_t len = strlen(fmt) + strlen(name);
  char* message = NEW_RESOURCE_ARRAY(char, len);
  jio_snprintf(message, len, fmt, name);
  Exceptions::_throw_msg(THREAD_AND_LOCATION,
    vmSymbols::java_lang_SecurityException()
, message);
}
修改该文件以去除掉相关限Ӟq按照本pd?a href="http://www.aygfsteel.com/jiangshachina/archive/2015/10/30/427994.html">W一文?/a>中介l的Ҏ(gu)去重新构Z个OpenJDK。那么,q个新的JDK不?x)再对包名有M限制?jin)?br />
3. 覆盖Java核心(j)APIQ?/strong>
开发者们在用主IDE时会(x)发现Q如果工E有多个jar文g或源文g目录中包含相同的c,q些IDE?x)根据用h定的优先U顺序来加蝲q些cR比如,在Eclipse中,右键点击某个Java工程-->属?->Java Build Path-->Order and ExportQ在q里调整各个cd或源文g目录的位|,卛_指定加蝲cȝ优先U?br />当开发者在使用某个开源类?jar文g)Ӟ惛_其中某个c进行修改,那么可以将该类的源代码复制出来Qƈ在Java工程中创Z个同名类Q然后指定Eclipse优先加息自己创徏的类。即Q在~译时与q行时用自己创徏的类去覆盖类库中的同名类。那么,是否可以如法炮制去覆盖Java核心(j)API中的cdQ?br />考虑去覆盖类java.util.HashMapQ只是简单在它的put()Ҏ(gu)d一条打印语。那么就需要将src.zip中的java/util/HashMap.java复制出来Qƈ在当前Java工程中创Z个同名类java.util.HashMapQƈ修改put()Ҏ(gu)Q如下所C:(x)
package java.util;

public class HashMap<K,V> extends AbstractMap<K,V>
    
implements Map<K,V>, Cloneable, Serializable {
    .
    
public V put(K key, V value) {
        System.out.printf(
"put - key=%s, value=%s%n", key, value);
        
return putVal(hash(key), key, value, falsetrue);
    }
    
}
此时Q在Eclipse环境中,SynchronizedHashMap使用的java.util.HashMap被认为是上述新创建的HashMapcR那么运行应用程序SyncMapTest后的期望输出应该如下所C:(x)
put - key=Key, value=Value
Value
但运行SyncMapTest后的实际输出却ؓ(f)如下Q?br />
Value
看v来,新创建的java.util.HashMapq没有被使用上。这是ؓ(f)什么呢Q能?惛_"到的原因q是cd载器。关于Javacd载器的讨Z(jin)本文的范_(d)而且关于该主题的文章已是汗牛充栋Q但本文仍会(x)q其要点?br />Javacd载器׃至上分ؓ(f)三个层次Q引导类加蝲?Bootstrap Class Loader)Q扩展类加蝲?Extension Class Loader)和应用程序类加蝲?Application Class Loader)。其中引导类加蝲器用于加载rt.jarq样的核?j)类库。ƈ且引导类加蝲器ؓ(f)扩展cd载器的父加蝲器,而扩展类加蝲器又为应用程序类加蝲器的父加载器。同时JVM在加载类时实行委托模式。即Q当前类加蝲器在加蝲cLQ会(x)首先委托自己的父加蝲器去q行加蝲。如果父加蝲器已l加载了(jin)某个c,那么子加载器不?x)再ơ加载?br />׃可知Q当应用E序试图加蝲java.util.MapӞ它会(x)首先逐向上委托父加载器d载该c,直到引导cd载器加蝲到rt.jar中的java.util.HashMap。由于该cdl被加蝲?jin),我们自己创徏的java.util.HashMap׃?x)被重复加蝲?br />使用java命o(h)q行SyncMapTestE序时加上VM参数-verbose:classQ会(x)在窗口中打印出Ş式如下的语句Q?br />
[Opened /home/ubuntu/jdk1.8.0_custom/jre/lib/rt.jar]
[Loaded java.lang.Object from /home/ubuntu/jdk1.8.0_custom/jre/lib/rt.jar]

[Loaded java.util.HashMap from /home/ubuntu/jdk1.8.0_custom/jre/lib/rt.jar]
[Loaded java.util.HashMap$Node from /home/ubuntu/jdk1.8.0_custom/jre/lib/rt.jar]

[Loaded java.util.SynchronizedHashMap from file:/home/ubuntu/projects/test/classes/]
Value
[Loaded java.lang.Shutdown from /home/ubuntu/jdk1.8.0_custom/jre/lib/rt.jar]
[Loaded java.lang.Shutdown$Lock from /home/ubuntu/jdk1.8.0_custom/jre/lib/rt.jar]
从中可以看出Q类java.util.HashMap实是从rt.jar中加载到的。但理论上,可以通过自定义类加蝲器去打破委托模式Q然而这是另一个话题(sh)(jin)?/div>


Sha Jiang 2015-11-01 20:06 发表评论
]]>
Play OpenJDK: 构徏你自qJDK(?http://www.aygfsteel.com/jiangshachina/archive/2015/10/30/427994.htmlSha JiangSha JiangFri, 30 Oct 2015 15:17:00 GMThttp://www.aygfsteel.com/jiangshachina/archive/2015/10/30/427994.htmlhttp://www.aygfsteel.com/jiangshachina/comments/427994.htmlhttp://www.aygfsteel.com/jiangshachina/archive/2015/10/30/427994.html#Feedback0http://www.aygfsteel.com/jiangshachina/comments/commentRss/427994.htmlhttp://www.aygfsteel.com/jiangshachina/services/trackbacks/427994.html
Play OpenJDK: 构徏你自qJDK

计划使Play OpenJDK成ؓ(f)一l介l如何用ƈ参与OpenJDK目的系列文章。本文是该系列的W一文章,它基于OpenJDK 8的源代码介绍?jin)构Z个属于自qJDKҎ(gu)?2015.10.30最后更?

1. OpenJDK
曄的Sun Microsystems. IncQ也是Java语言的发明者,它的JDK代码贡献出来Q成立了(jin)一个开源项目,?a >OpenJDK?br />    同时Q它也是一个社区。相关的公司Q组l和个h在这个社Z协作开发OpenJDK。社区根据不同的领域或项目提供了(jin)一pd?a >邮g列表Q利益相x(chng)或对其感兴趣的个人都可以订阅q些邮g列表去进行关注和讨论。例如,Java核心(j)API的邮件列表是core-libs-dev@openjdk.java.netQ关于java.langQjava.util{核?j)API的新Ҏ(gu)都?x)在q里q行讨论Qƈ对其最l的实现代码q行审查。Q何将要进入OpenJDK版本库的源代码,无论是品代?卻I要随JDK发布的程?Q还是测试代码,都需要在C֌中进行公开的代码审查?br />    选择一个自己感兴趣的领域或目Q加入它的邮件列表,长期跟踪它的发展Q看着专家们的讨论、争论推动JDK的演q,学习(fn)开发者们的API设计与代码实玎ͼ...Q这些对自己的成镉K是极有帮助的。也许,q能看到一些有的八卦;-)

2. 准备工作
在几U主操作系l,Linux(如Ubuntu和Fedora)QW(xu)indows(7?)QMacOS(Lion和Moutain Lion)Q中都可以构建OpenJDKQ具体的l节可以参见官方的一文?/a>?br />    本文选择使用Ubuntu 14.04。坦白地_(d)选择使用UbuntuQ实是因为在Linux环境中构建OpenJDK非常单。若在Windows中进行构建,则需要安装Visual Studio C++~译器。MacOSQ嗯Q我没有MBP。可能更多hqx(chng)是用WindowsQ但安装一个Linux也不ȝ(ch)。先安装免费的VM工具VirtaulBoxQ再M载Ubuntu?a >ISO文gQ然后用VirtualBoxd装Ubuntu。VirtualBox单易用,|上的相兌料也非常的多?br />    OpenJDK的源文g版本库基?a >Mercurial(hg)Q它是一个与Git怼的分布式版本控制工具。在Ubuntu中安装Mercurial只需要执行命?br />
$ sudo apt-get install mercurial
    OpenJDK中各目的源代码版本库的路径均在http://hg.openjdk.java.net/之下Q在q里可以扑ֈ6Q?Q?Q?和Jigsaw的源代码。其中JDK 8的最新开发版本库路径为http://hg.openjdk.java.net/jdk8u/jdk8u-dev/?br />    另外Q构建OpenJDK旉要一个启动JDKQ本文选择构徏OpenJDK 8Q那么启动JDK的版本应不低??br />
3. 下蝲源代?/span>
克隆版本库,
$ hg clone http://hg.openjdk.java.net/jdk8u/jdk8u-dev/ jdk8-src
requesting all changes
adding changesets
adding manifests
adding file changes
added 
1570 changesets with 1958 changes to 141 files
updating to branch default
85 files updated, 0 files merged, 0 files removed, 0 files unresolved
q入源代码目?br />
$ cd jdk8-src/
OpenJDK的源代码版本库实际上包含多个独立的子版本库,需要执行如下脚本去分别下蝲各个子版本库的源代码Q?br />
$ sh get_source.sh
# Repositories:  corba jaxp jaxws langtools jdk hotspot nashorn
                corba:   hg clone http://hg.openjdk.java.net/jdk8u/jdk8u-dev/corba corba
                 jaxp
:   hg clone http://hg.openjdk.java.net/jdk8u/jdk8u-dev/jaxp jaxp
                corba
:   requesting all changes
                 jaxp
:   requesting all changes

4. 构徏
调用configureq行预构建,其中的参?-with-boot-jdk用于指定启动JDK的\径。如果启动JDK的java命o(h)已存在于PATH环境变量中,该参数可以忽略?br />
$ sh configure --with-boot-jdk=/path/to/boot/jdk
该过E会(x)(g)构建环境是否符合要求,如有问题Q它?x)给出提C。比如,
configure: error: Could not find X11 libraries. You might be able to fix this by running 'sudo apt-get install libX11-dev libxext-dev libxrender-dev libxtst-dev libxt-dev'.
此时Ҏ(gu)提示安装所需要的库即可。再重新执行上述configure命o(h)Q可能还?sh)(x)提C缺其它的库,那么再次Ҏ(gu)提示q行安装。如此反复,只到预构建成功完成?br />最后就是进行构建,直接执行如下命o(h)Q?br />
$ make all
在此q程中可以会(x)遇到一些警告,不必理会(x)Q耐心(j){待...完成后,?x)出现如下的汇M息,
----- Build times -------
Start 2015-10-30 22:11:10
End   2015-10-30 22:52:54
00:01:01 corba
00:01:08 demos
00:06:49 docs
00:19:37 hotspot
00:01:47 images
00:00:35 jaxp
00:00:49 jaxws
00:08:23 jdk
00:01:09 langtools
00:00:25 nashorn
00:41:44 TOTAL
-------------------------
Finished building OpenJDK for target 'all'
在当前\径下?x)生成一个build目录Q构建好的JDK在那里面。新JDK的具体\径类gbuild/linux-x86_64-normal-server-release/images/jdk。可以执行如下命令去试q个JDKQ?br />
$ build/linux-x86_64-normal-server-release/images/jdk/bin/java -version
openjdk version "1.8.0-internal"
OpenJDK Runtime Environment (build 1.8.0-internal-ubuntu_2015_10_30_22_07-b00)
OpenJDK 64-Bit Server VM (build 25.66-b00, mixed mode)


Sha Jiang 2015-10-30 23:17 发表评论
]]>
վ֩ģ壺 ¡| ۽| ͼ| | | SHOW| | γ| ƽ| ĩ| | | ˮ| | ̨| | | | | | | | ĵ| Ϫ| ŷ| | | | ͼ| | | | ɽ| Һ| | Ͱ| ȫ| | | | |