[讨论] 一些底层问题,比较零散
gooooooooa
2012-02-12
最近在回顾 Java IO 笔记本是mac,平台是openjdk6.
public FileOutputStream(File file, boolean append) throws FileNotFoundException 里面有这么一句: this.fd = new FileDescriptor(); 再看 FileDescriptor() public FileDescriptor() { fd = -1; useCount = new AtomicInteger(); } 生成一个无效的 FileDescriptor 问题来了:这里生成一个无效的 FileDescriptor 意义在哪里? 还有想请教,当在深入底层看一些java的机制时,必定会深入到native的代码。 此时,环境是如何的,开一个eclipse-->jdk源码 再开一个 vs或者vim/emacs-->native c ? 一般研究这些底层代码时,较常用的一些工具是什么。 源码定位问题,比如我想看 java 遇到 synchronized时,他底层是怎么去做的,是编译时就翻译成另一个东西? 像 Cloneable 和 Serializable 这种标记接口,java又是如何去判断处理的。 要看这些机制,源码在哪里,如何快速定位 |
|
RednaxelaFX
2012-02-13
1、我手上没Mac版JDK的代码。它跟BSD版的代码更接近,而跟Linux版的的区别大一些。
Anyway,我从Linux版来告诉你这里发生什么事了。 FileOutputStream.java里有个open()方法的声明。它的定义在native代码里。 JNIEXPORT void JNICALL Java_java_io_FileOutputStream_openAppend(JNIEnv *env, jobject this, jstring path) { fileOpen(env, this, path, fos_fd, O_WRONLY | O_CREAT | O_APPEND); } void fileOpen(JNIEnv *env, jobject this, jstring path, jfieldID fid, int flags) { WITH_PLATFORM_STRING(env, path, ps) { FD fd; #ifdef __linux__ /* Remove trailing slashes, since the kernel won't */ char *p = (char *)ps + strlen(ps) - 1; while ((p > ps) && (*p == '/')) *p-- = '\0'; #endif fd = JVM_Open(ps, flags, 0666); if (fd >= 0) { SET_FD(this, fd, fid); } else { throwFileNotFoundException(env, path); } } END_PLATFORM_STRING(env, ps); } /* * Macros to set/get fd from the java.io.FileDescriptor. These * macros rely on having an appropriately defined 'this' object * within the scope in which they're used. * If GetObjectField returns null, SET_FD will stop and GET_FD * will simply return -1 to avoid crashing VM. */ #define SET_FD(this, fd, fid) \ if ((*env)->GetObjectField(env, (this), (fid)) != NULL) \ (*env)->SetIntField(env, (*env)->GetObjectField(env, (this), (fid)),IO_fd_fdID, (fd)) 如果上面这几段代码你能看懂,那么你应该可以发现这里的native code在“干坏事”,在open()过程中它会强行设置那个FileDescriptor实例里的字段。就像通过反射去设置了一个private字段一样。所以那个FileDescriptor实例不是无用的,里面设置到-1是为了避免跟有效的fd冲突,以便判断文件到底是不是正常打开了。 ============================= 我很土,看OpenJDK代码的时候通常就是用SciTe或者vim。已经越来越少用IDE了。我基本上只在做纯Java的工程的时候才开Eclipse。 SciTe的文件中搜索挺好用的,基本上就像是方便的grep前端。 ============================== 引用 要看这些机制,源码在哪里,如何快速定位 嗯这个问题很大…我不知道该从哪里开始。 例如synchronized,首先我会通过规范知道Java的synchronized关键字在JVM规范里规定要用配对的monitorenter/monitorexit来表示。然后我会去找找看各种JVM实现里这俩字节码是如何实现的。先在源码里文本搜索,然后慢慢缩小范围找到实际的实现;如果能配合调试那是最好。 |
|
haoweishow
2012-02-13
引用 我很土,看OpenJDK代码的时候通常就是用SciTe或者vim。已经越来越少用IDE了。我基本上只在做纯Java的工程的时候才开Eclipse。 SciTe的文件中搜索挺好用的,基本上就像是方便的grep前端。 请问R大,你们开发也都是用vim,SciTe吗?我在ubuntu(宿主win7,在ubuntu虚拟系统中搭建的开发环境)上安装netbeans,引入openjdk的源码,编译都是OK的。唯一的缺陷就是贼慢。 另外还有个慢就是,我每修改一次hotspot的代码,对项目进行build,都要花费20+分钟。撇开我的硬件配置,请问R大,如何提高这个效率呀? |
|
RednaxelaFX
2012-02-13
我开发就是用vim。而且我没特别配置过vimrc,很土。这方面别学我。
![]() ========================= 撇开你的硬件配置我也不知道怎样能更快 我用来编译HotSpot VM的机器是16核的Xeon,编译的时候带上HOTSPOT_BUILD_JOBS=16,完全干净的build一次HotSpot VM大概1分钟,只改了少量cpp文件的时候增量编译瞬间就好了。所以编译不太痛苦… 我在笔记本上编译HotSpot VM也不是特别痛苦。上一代i5,8GB内存,开HOTSPOT_BUILD_JOBS=4干净build一次HotSpot VM大概是不到4分钟。 不知道你说的build一次要20分钟是整个OpenJDK都build了还是只build了HotSpot。如果是前者的话那真是神速…不过看样子应该是后者吧。你还是找台实体机弄点稍微好些的配置来跑吧。在虚拟机里build慢是正常的。 |
|
haoweishow
2012-02-13
我修改了hotspot的代码,重新执行make的时候,发现时间消耗在JDK上面了。
修改make脚本: make debug_build BUILD_JAXWS=false BUILD_JAXP=false BUILD_JDK=false 速度快很多,1~4分钟不等,以前BUILD_JDK就花了18分钟左右。 以后还是用脚本老老实实make,再也不用netbeans来make了。 PS:讨论这个有点喧宾夺主,请楼主请不要介意! 谢谢R大的回复。 ![]() |
|
RednaxelaFX
2012-02-13
其实你可以直接在hotspot目录里make的咯,那样自然就不会去build出JDK的其它部分,就很快,也不用指定BUILD_XXX=false
|
相关讨论
相关资源推荐
- HP-Socket-v3.2.1-rc3源码
- 高性能 Socket 组件 HP-Socket v3.2.1 正式发布
- 高性能 Socket 组件 HP-Socket v3.2.1-RC3 公布
- 高性能 Socket 组件 HP-Socket v3.2.1-RC4 发布
- 高性能 Socket 组件 HP-Socket v3.2.1-RC1 公布
- 高性能 Socket 组件 HP-Socket v3.2.1-RC2 发布
- 高性能 Socket 组件 HP-Socket v3.2.1-RC5 发布
- 高性能 Socket 组件 HP-Socket v3.2.1 正式公布
- 高性能 Socket 组件 HP-Socket v3.2.1-RC1 发布
- 高性能 Socket 组件 HP-Socket v3.2.1-RC3 发布