第一篇: openJDK源码编译安装--mac版本

参考文章: 

a. https://blog.csdn.net/manageer/article/details/72812149

b.https://blog.csdn.net/lizhengjava/article/details/60138890

c.https://www.cnblogs.com/Seeasunnyday/p/9368302.html(主要是参考这篇文章,但是包error  # <iostream> not found,后来有参考的其他文章解决这个问题)

 

 

 

1.为什么要编译JDK

  想要一探JDK内部的实现机制,最便捷的路径之一就是自己编译一套JDK,通过阅读和跟踪调试JDK源码去了解Java技术体系的原理,虽然门槛高一点,但肯定比阅读各种书籍,文章,博客更在贴切一点,另外,JDK的很多方法都是本地化(Native)的,需要跟踪这些方法的运作或对JDK进行Hack的时候,都需要自己编译一套JDK。
 

2.选择JDK

  现在网上有不少开源的JDK实现可以供我们选择,如Apache Harmony,OpenJDK等,考虑到Sun系列的JDK是现在使用得最广泛的JDK版本,所以我们选择openJDK进行编译。
关于openJDK?
  openJDK是sun在2006年末把java开源而形成的项目。开源是通常意义上的源码形式上开放,等同于源码可被复用。商业版的oracle jdk和open jdk 除了版权注释之外,其余代码基本上都是相同的,都是建立在两者共有的组件基础上。oracle jdk还会存在一些open jdk没有的,商用闭源的功能。oracle的项目发布经理Joe Darcy 在OSCON2011 上对两者的关系上也证实了oracle jdk和open jdk程序上市非常接近。
 
 

3.环境准备

1.openJDK下载,获取openJDk源码有两种方式.
  (1)其中一种是通过一款代码版本管理Mercurial上获取
    hg clone http://hg.openjdk.java.net/jdk8/jdk8 jdk8
    cd jkd8
    bash ./get_source.sh
  这种是最直接的方式,但是由于文件很多,国内的网络对Mercurial不如对git svn上不够快,经常可能失败,可以把镜像换成国内的,这个可以自己找找。
  (2)从https://download.java.net/openjdk/jdk8直接下载打包好的源码文件,这里openjdk在下载源码有个bug,如图:
  

把这里的下载地址前面的域名弄错了,应该是http://download.java.net,把前面的http://www.java.net/download/换掉,后面的不变,就能下载打包好的源码文件。参考1.7地址: http://download.java.net/openjdk/jdk7/promoted/b147/openjdk-7-fcs-src-b147-27_jun_2011.zip
最终的地址: http://download.java.net/openjdk/jdk8/promoted/b132/openjdk-8-src-b132-03_mar_2014.zip
 
我采用的第二种方式
 
2.安装依赖软件,如果没有brew命令,可以先看看brew怎么安装再继续执行以上安装命令。
(1)Xcode-select:安装命令:xcode-select –install  进行x11链接
sudo ln -s /usr/X11/include/X11 /usr/include/X11 or sudo ln -s /usr/local/X11/include/X11 /usr/include/X11  (如果软连接失败,重启mac时按住command+R 进入恢复模式,然后打开terminal  执行 csrutil disable,再重启,这是mac对安全的一种校验)
注: 这里重点说一句: 重启mac时按住command+R 进入恢复模式. 在弹出的面板上是没有终端的,终端要去上面的菜单栏选择. 
其他: 如果不知道xcode-select是什么,可以参考这篇文章: https://blog.csdn.net/chenyufeng1991/article/details/47007979
(2)安装XQuartz 下载地址: https://www.xquartz.org/
(3)安装freetype,安装命令:brew install freetype
(4)安装GC 安装命令: brew install gcc49 据说安装往上的版本会报错。
(5) 安装ccache提升编译速度 brew install ccache
(6) 安装ant 一般mac都会有这个环境,如果没有执行:brew install ant
 
 我只安装了Xcode-select,在源码make install的时候报异常 # <iostream> not found. 找了好久解决办法也没找到,但感觉和Xcode有关系. 所以,开始安装Xcode.
 
3.修改源码

(1). 修改generated-configure.sh(路径:common/autoconf/generated-configure.sh)
  注释20061行
  // as_fn_error $? "GCC compiler is required. Try setting --with-tools-dir." "$LINENO" 5
  注释21640行
  // as_fn_error $? "GCC compiler is required. Try setting --with-tools-dir." "$LINENO" 5

 

(2). 修改relocInfo.hpp(路径:hotspot/src/share/vm/code/relocInfo.hpp)
  修改367行
  inline friend relocInfo prefix_relocInfo(int datalen);
  修改472行
  inline relocInfo prefix_relocInfo(int datalen = 0) {
    assert(relocInfo::fits_into_immediate(datalen),"datalen in limits");
    return relocInfo(relocInfo::data_prefix_tag,relocInfo::RAW_BITS,relocInfo::datalen_tag | datalen);
  }


(3). 修改openjdk/hotspot/src/share/vm/opto/loopPredicate.cpp
  修改775行为
  assert(rng->Opcode() == Op_LoadRange || _igvn.type(rng)->is_int()->_lo >= 0,"must be");


 (4).修改openjdk/hotspot/src/share/vm/runtime/virtualspace.cpp
  修改331行为
  if (base() != 0) {

4.设置环境变量

  cd ~
  open .bash_profile (这个在安装jdk都会设置的,如果没有这个文件去看看jdk安装的教程)
添加变量:


# 设定语言选项,必须设置
export LANG=C
# Mac平台,C编译器不再是GCC,是clang
export CC=clang
# 跳过clang的一些严格的语法检查,不然会将N多的警告作为Error
export COMPILER_WARNINGS_FATAL=false
# 链接时使用的参数
export LFLAGS='-Xlinker -lstdc++'
# 是否使用clang
export USE_CLANG=true
# 使用64位数据模型
export LP64=1
# 告诉编译平台是64位,不然会按32位来编译
export ARCH_DATA_MODEL=64
# 允许自动下载依赖
export ALLOW_DOWNLOADS=true
# 并行编译的线程数,编译时间长,为了不影响其他工作,我选择为2
export HOTSPOT_BUILD_JOBS=2
export ALT_PARALLEL_COMPILE_JOBS=2
# 是否跳过与先前版本的比较
export SKIP_COMPARE_IMAGES=true
# 是否使用预编译头文件,加快编译速度
export USE_PRECOMPILED_HEADER=true
# 是否使用增量编译
export INCREMENTAL_BUILD=true
# 编译内容
export BUILD_LANGTOOLS=true
export BUILD_JAXP=true
export BUILD_JAXWS=true
export BUILD_CORBA=true
export BUILD_HOTSPOT=true
export BUILD_JDK=true
# 编译版本
export SKIP_DEBUG_BUILD=true
export SKIP_FASTDEBUG_BUILD=false
export DEBUG_NAME=debug
# 避开javaws和浏览器Java插件之类的部分的build
export BUILD_DEPLOY=false
export BUILD_INSTALL=false

最后干掉这两个变量,不然会有诡异的事发生
unset JAVA_HOME
unset CLASSPATH

 将变量添加到base_profile以后,把中午注释去掉,否则会乱码,编译报错

5.编译,( 遇到问题可以先看看下面的问题描述)

(1)cd 到下载好的openSDK目录下,先授予权限给openJDK目录 如: chmod -R 777 openjdk
 
(2)./configure 如果找不freetype 可以执行./configure --with-freetype-include=/usr/local/include/freetype2 --with-freetype-lib=/usr/local/lib/
 

sh configure --with-debug-level=slowdebug --with-boot-jdk=`/usr/libexec/java_home -v 1.8` --with-freetype-include=/usr/local/include/freetype2 --with-freetype-lib=/usr/local/lib/ --with-target-bits=64 --with-jvm-variants=server --with-jdk-variant=normal --with-milestone=internal --with-update-version=b25 --with-build-number=b25 --with-zlib=system --with-num-cores=2 --with-jobs=4 CC=clang CXX=clang++

 

sh configure --with-debug-level=slowdebug --with-target-bits=64 --with-jvm-variants=server --with-jdk-variant=normal --with-milestone=internal --with-update-version=b25 --with-build-number=b25 --with-num-cores=2 --with-jobs=2 CC=clang CXX=clang++ --with-freetype-include=/usr/local/include/freetype2 --with-freetype-lib=/usr/local/lib/ --with-boot-jdk=/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home --enable-ccache

1

 

————————————————
版权声明:本文为CSDN博主「ykd2020」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/yuankundong/article/details/78876523

 

 

使用这种方式编译,在build文件夹生成两个文件. 如果使用第一种,只会生成一个

参考文章: https://blog.csdn.net/lizhengjava/article/details/60138890

 
  (3) 开始执行make命令: 在执行make命令需要指定编译环境,环境路径在:./openjdk/build/下面 一般有两个 macosx-x86_64-normal-server-release 和 macosx-x86_64-normal-server-slowdebug
  如果一般编译失败会有失败的文件,为了保险起见先执行:
    make CONF=macosx-x86_64-normal-server-release clean 或者
    make CONF=macosx-x86_64-normal-server-slowdebug clean
  再执行:
    make CONF=macosx-x86_64-normal-server-release install 或者
    make CONF=macosx-x86_64-normal-server-slowdebug install
 
make COMPILER_WARNINGS_FATAL=false LFLAGS='-Xlinker -lstdc++' CC=clang USE_CLANG=true LP64=1
 
我使用的是第一个: make CONF=macosx-x86_64-normal-server-release clean因为我的文件夹下没有第二个
编译成功如图:
  

6.我执行./configure和编译遇到的问题:

问题1和问题2是原作者遇到的,我并没有遇到. 后面的问题是我遇到的

(1)./configure问题: configure: error: GCC compiler is required
  解决方法:
   jdk8/common/autoconf/generated-configure.sh文件中 注释两处代码:第20061,21640行 #as_fn_error $? "GCC compiler is required. Try setting --with-tools-dir." "$LINENO" 5
 
  (2)make问题:
  Running nasgen
  Exception in thread "main" java.lang.VerifyError:
  class jdk.nashorn.internal.objects.ScriptFunctionImpl overrides final method setPrototype.(Ljava/lang/Object;)V
  解决方法:
  修改:vim ./openJDk/nashorn/make/BuildNashorn.gmk
  80行原来 -cp 修改为:-Xbootclasspath/p:  如图: 
  
 (3) 在执行sudo ln -s /usr/X11/include/X11 /usr/include/X11 的时候提示: sudo: /usr/bin/sudo must be owned by uid 0 and have the setuid bit set
 
  这个问题的原因是提示sudo没有权限,最终结觉办法是,使用root用户登录. 然后将/usr/bin/sudo 授与4755权限
  如果不知道怎么使用root用户登录,可以看这篇文章: https://www.jianshu.com/p/be9f1d57c710.   我是重置了root的密码,因为不知道原密码是什么,然后退出当前用户,使用root重新登录. 
  执行: chmod 4755 /usr/bin/sudo 就可以使用了
 
  (4) 在root用户授权sudo以后,回到luo***用户登录的时候,终端显示异常. 内容如下:

  Could not determine audit condition  [Process completed]

  [进程已完成]

   处理办法参考: https://www.jianshu.com/p/d764d2840071. 很多说是因为./bash_profile文件配置错误导致的,但我这个不是. 将/usr/bin 下的login文件改名login1,再打开终端,然后执行

  sudo chown root:wheel /usr/bin/login

  sudo chmod u+s /usr/bin/login

  在将login1的名字改回login. 已经恢复了.

 

 (4) 报异常<iostream> not found. 这个问题应该是和Xcode没有进行软链有关系. 我第一次操作的时候没有进行软链
 /Users/luoxiaoli/java/openjdk/hotspot/src/share/vm/adlc/adlc.hpp:35:10: fatal error: 'iostream' file not found

#include <iostream>

         ^~~~~~~~~~

 

 

 

 

7.测试是否编译成功
  cd ./openjdk/build/macosx-x86_64-normal-server-release/jdk/bin
  执行java -version
  如图则编译成功:
   
 
 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


jinfo 命令可以用来查看 Java 进程运行的 JVM 参数,命令如下:[root@admin ~]# jinfo --helpUsage: jinfo [option] &lt;pid&gt; (to connect to running process) jinfo [option] &lt;executable &lt;core&gt; (to connect to a core file) jinfo [option] [serve
原文链接:https://www.cnblogs.com/niejunlei/p/5987611.htmlJava Virtual Machine Stacks,线程私有,生命周期与线程相同,描述的是Java方法执行的内存模型:每一个方法执行的同时都会创建一个栈帧(Stack Frame),由于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法的执行就对应着栈帧在虚拟机栈中的入栈,出栈...
java 语言, 开发者不能直接控制程序运行内存, 对象的创建都是由类加载器一步步解析, 执行与生成与内存区域中的; 并且jvm有自己的垃圾回收器对内存区域管理, 回收; 但是我们已经可以通过一些工具来在程序运行时查看对应的jvm内存使用情况, 帮助更好的分析与优化我们的代码;jps查看系统中有哪些java进程jps 命令类似与 linux 的 ps 命令,但是它只列出系统中所有的 Java 应用程序。 通过 jps 命令可以方便地查看 Java 进程的启动类、传入参数和 Java 虚拟机参数等信息
1.jvm的简单抽象模型:  2.类加载机制     双亲委派模型是为了防止jdk核心类库被篡改,如果需要打破可以重写Classloader.loadClass方法。r 双亲委派模型:一个类加载器收到一个类的加载请求,他会先判断自身是否已存在该类,如果不存在上抛给上一级类加载器ClassLoad
堆外内存JVM启动时分配的内存,称为堆内存,与之相对的,在代码中还可以使用堆外内存,比如Netty,广泛使用了堆外内存,但是这部分的内存并不归JVM管理,GC算法并不会对它们进行回收,所以在使用堆外内存时,要格外小心,防止内存一直得不到释放,造成线上故障。堆外内存的申请和释放JDK的ByteBuffe
1.springboot和tomcat2.springcloud的请求如何通过网关鉴权?3.springmvc启动时组件的加载顺序?4.mybatis如何同时更新三条记录5.hibernate实现级联更新6.一个web程序应用程序启动时的加载流程7.如何向www.baidu.com地址发出请求时,并获取相应?8.???9.谈谈你对tcp/iptelnetudp协
堆设置-Xms256M:初始堆大小256M,默认为物理内存的1/64-Xmx1024M:最大堆大小1024M,默认为物理内存的1/4,等于与-XX:MaxHeapSize=64M-Xmn64M:年轻代大小为64M(JDK1.4后支持),相当于同时设置NewSize和MaxNewSize为64M-XX:NewSize=64M:初始年轻代大小-XX:MaxNewSize=256M:最大年轻代大小(默认
一.概述收集算法(JVM之垃圾回收-垃圾收集算法)是内存回收的抽象策略,垃圾收集器就是内存回收的具体实现。JVM规范对于垃圾收集器的应该如何实现没有任何规定,因此不同的厂商、不同版本的虚拟机所提供的垃圾收集器差别较大,这里只看HotSpot虚拟机。就像没有最好的算法一样,垃圾收集器
Java中的堆是JVM所管理的最大的一块内存空间,主要用于存放各种类的实例对象,如下图所示: 在Java中,堆被划分成两个不同的区域:新生代(Young)、老年代(Old)。新生代(Young)又被划分为三个区域:Eden、S0、S1。 这样划分的目的是为了使JVM能够更好的管理堆内存中的对象,包
JVM深入理解JVM(4)——如何优化JavaGC「译」 PostedbyCrowonAugust21,2017本文翻译自SangminLee发表在Cubrid上的”BecomeaJavaGCExpert”系列文章的第三篇《HowtoTuneJavaGarbageCollection》,本文的作者是韩国人,写在JDK1.8发布之前,虽然有些地
 JVM深入理解JVM(2)——GC算法与内存分配策略 PostedbyCrowonAugust10,2017说起垃圾收集(GarbageCollection,GC),想必大家都不陌生,它是JVM实现里非常重要的一环,JVM成熟的内存动态分配与回收技术使Java(当然还有其他运行在JVM上的语言,如Scala等)程序员在提升开
运行时数据区  线程独有本地方法栈、虚拟机栈、程序计数器这些与线程对应的数据区会随着线程开始和结束创建和销毁  整体公有元数据区(又称方法区)、堆区会随着虚拟机启动而创建,随着虚拟机退出而销毁 
java整个堆大小设置:Xmx和Xms设置为老年代存活对象的3-4倍,即FullGC之后的老年代内存占用的3-4倍。永久代PermSize和MaxPermSize设置为老年代存活对象的1.2-1.5倍年轻代Xmx的设置为老年代存活对象的1-1.5倍老年代的内存大小设置为老年代存活对象的2-3倍BTW: Sun官方建议年轻代
栈顶缓存(Top-of-StackCashing)技术基于栈式架构得虚拟机所使用的零地址指令更加紧凑,但完成一项操作的时候必然使用更多的入栈和出栈指令,这同时也就意味着将需要更多的指令分派次数和内存读写次数 由于操作数是存储在内存重的,因此频繁地执行内存读/写操作必然影响速度。 综上
自用。同样的代码在不同的平台生成的机器码是不一样的,为什么java代码生成的字节码文件,能在不同的平台运行?因为不同版本的jdk里面的虚拟机会屏蔽不同操作系统在底层硬件与指令上的区别。栈:线程栈,局部变量存放栈内存区域。线程(分配一个栈)运行分配栈将局部变量放入内存。怎么放:栈
jconsole监控:1.java启动命令加上参数java-Djava.rmi.server.hostname=172.16.17.247-Dcom.sun.management.jmxremote-Dcom.sun.management.jmxremote.port=2099-Dcom.sun.management.jmxremote.authenticate=false-Dcom.sun.management.jmxremote.ssl=false -XX:+Unlock
类加载器分类publicclassStackStruTest{publicstaticvoidmain(String[]args){//对用户自定义个类来说:默认使用系统类加载器进行加载-----AppClassLoaderClassLoaderclassLoader=StackStruTest.class.getClassLoader();System.out.p
堆体系结构一个JVM实例只存在一个堆内存,堆内存的大小是可调节的。类加载器读取类文件后,需要把类、方法、常量、变量放在堆内存中,保存所有引用类型的真实信息,以方便执行器指向,堆内存分为三个部分:年轻代、老年代、永久代。Java7之前,堆内存在逻辑上分为:年轻代、老年代、永久代。物
JVM深入理解JVM(5)——虚拟机类加载机制 PostedbyCrowonAugust21,2017在Class文件中描述的各种信息,最终都需要加载到虚拟机中之后才能运行和使用。而虚拟机中,而虚拟机如何加载这些Class文件?Class文件中的信息进入到虚拟机中会发生什么变化?本文将逐步解答这
保存(持久化)对象及其状态到内存或者磁盘Java平台允许我们在内存中创建可复用的Java对象,但一般情况下,只有当JVM处于运行时,这些对象才可能存在,即,这些对象的生命周期不会比JVM的生命周期更长。但在现实应用中,就可能要求在JVM停止运行之后能够保存(持久化)指定的对象,并在