《深入理解java虚拟机》第1章 走近Java

1.6实战:自己编译JDK
想要一探JDK内部的实现机制,最便捷的路径之一就是自己编译- -套JDK,通过阅读和跟踪调试JDK源码去了解Java技术体系的原理,虽然门槛会高一点,但肯定会比阅读各种书籍、文章更加贴近本质。另外,JDK中的很多底层方法都是本地化(Native) 的,需要跟踪这些方法的运作或对JDK进行Hack的时候,都需要自己编译套JDK。现在网络上有不少开源的JDK实现可以供我们选择,如Apache Harmony. OpenJDK等。考虑到Sun系列的JDK是现在使用得最广^泛的JDK版本,笔者选择了OpenJDK进行这次编
译实战。

1.6.1 获取JDK源码
首先要先明确OpenJDK和Sun/OracleJDK之间,以及OpenJDK 6、OpenJDK 7、OpenJDK 7u和OpenJDK 8等项目之间是什么关系,这有助于确定接下来编译要使用的JDK版本和源码分支。从前面介绍的Java发展史中我们了解到OpenJDK是Sun在2006年末把Java开源而形成的项目,这里的“开源”是通常意义上的源码开放形式,即源码是可被复用的,例如IcedTea 9、UltraViolet9都 是从OpenJDK源码衍生出的发行版。但如果仅从“开源”字面意义(开放可阅读的源码)上看,其实Sun自JDK 1.5之后就开始以Java Research License(JRL)的形式公布过Java源码,主要用于研究人员阅读(JRL许可证的开放源码至JDK1.6 Update 23为止)。把这些JRL许可证形式的Sun/OracleJDK源码和对应版本的OpenJDK源码进行比较,发现除了文件头的版权注释之外,其余代码基本上都是相同的,只有字体渲染部分存在一点差异,OracleJDK采用了商业实现,而OpenJDK使用的是开源的FreeType。当然,“相同”是建立在两者共有的组件基础上的,Oracle JDK中还会存在- - 些Open JDK没有的、商用闭源的功能,例如从JRockit移植改造而来的Java Flight Recorder。预计以后JRockit 的MissionControl移植到HotSpot之后,也会以Oracle JDK专有、闭源的形式提供。

 Oracle的项目发布经理JoeDarcy在OSCON2011.上对两者关系的介绍9也证实了OpenJDK7和OracleJDK7在程序上是非常接近的,两者共用了大量相同的代码(如图1-6所示,注意图中提示了两者共同代码的占比要远高于图形上看到的比例),所以我们编译的OpenJDK,基本上可以认为性能、功能和执行逻辑上都和官方的Oracle JDK是-致的。

 

 是始于JDK 6时期,当时JDK 6和JDK 6 Update 1已经发布,JDK 7已经开始研发了,所以OpenJDK7是直接基于正在研发的JDK7源码建立的。但考虑到OpenJDK7的状况在当时还不适合实际生产部署,因此在OpenJDK 7 Build 20的基础上建立了OpenJDK 6分支,剥离掉JDK 7新功能的代码,形成-一个可以通过TCK 6测试的独立分支。2012年7月,JDK 7正式发布,在OpenJDK中也同步建立了OpenJDK 7 Update项目对JDK 7进行更新升级,以及OpenJDK 8项目开始下一个JDK大版本的研发。按照开发习惯, .新的功能或Bug修复通常是在最新分支上进行的,当功能或修复在最新分支上稳定之后会同步到其他老版本的维护分支.上。OpenJDK 6、OpenJDK 7、OpenJDK 7u和OpenJDK 8的源码都可以在它们相应的网页上找到,在本次编译实践中,笔者选用的项目是OpenJDK 7u,版本为7u6。获取OpenJDK源码有两种方式,其中一种是通过Mercurial代码版本管理工具从
Repository中直接取得源码(Repository 地址: htp://hg.openjdk java.net/jdk7u/jdk7u),获取过程如以下代码所示。

这是最直接的方式,从版本管理中看变更轨迹比看Release Note效果更好。但不足之处是速度太慢,虽然代码总容量只有300 MB左右,但是文件数量太多,在笔者的网络下全部复制到本地需要数小时。另外,考虑到Mercurial不如Git、SVN、ClearCase 或CVS之类的版本控制工具那样普及,对于一般读者,建议采用第二种方式,即直接下载官方打包好的源码包,读者可以从Source Bundle Releases页面(地址: htp://jdk7 java.net/source.html)取得打包好的源码,到本地直接解压即可。一般来说,源码包大概- - 至两个月左右会更新--次,虽然不够及时,但比起从Mercurial复制代码的确方便和快捷许多。笔者下载的是OpenJDK 7 Update 6 Build b21版源码包,2012 年8月28日发布,大概99MB,解压后约为339MB. 

1.6.2系统需求
如果可能,笔者建议尽量在Linux、MacOS或Solaris上构建OpenJDK,这要比在Windows平台上容易得多,本章实战中笔者将以Ubuntu 10.10 和MacOS x 10.8.2 为例进行构建。如果读者- -定要在 Windows平台上完成编译,可参考本书附录A,该附录是本书第- -版中介绍如何在Windows下编译OpenJDK 6的例子,原有的部分内容现在已经过时了(例如安装Plug部分),但还是有一-定参考意义,因此笔者没有把它删除掉,而是移到附录之中。无论在什么平台下进行编译,都建议读者认真阅读- - 遍源码中的README-builds .html文档(无论在OpenJDK网站上还是在下载的源码包中都有这份文档),因为编译过程中需要注意的细节非常多。虽然不至于像文档上所描述的“Building the source code for the JDKrequires a high level of technical expertise. Sun provides the source code primarily for technical experts who want to conduct research. ( 编译JDK需要很高的专业技术,Sun 提供JDK源码是为了技术专家进行研究之用)”那么夸张,但是如果读者是第一- 次编译,那有可能会在一些小问题上耗费许多时间。在本次编译中采用的是64位操作系统,编译的也是64位的OpenJDK,如果需要编译32位版本,那建议在32位操作系统上进行。在官方文档上写到编译OpenJDK至少需要512MB的内存和600MB的磁盘空间。512MB的内存也许能凑合使用,不过600MB的磁盘空间估计仅是指存放OpenJDK源码所需的空间,要完成编译,600MB肯定是无论如何都不够的,光输出的编译结果就有近3GB (因为有很多中间文件,以及会编译出不同优化级别( Product、Debug、 FastDebug 等)的虚拟机),建议读者至少保证5GB以上的空余磁盘。

对系统的最后一点要求就是所有的文件,包括源码和依赖项目,都不要放在包含中文的目录里面,这样做不是一-定不可以,只是没有必要给自己找麻烦。

1.6.3构建编译环境
在MacOSe和Linux上构建OpenJDK编译环境比较简单(相对于Windows来说),对于Mac OS,需要安装最新版本的XCode和Command Line Tools for XCode,在Apple Developer网站(https : //developer.apple.com/). 上可以免费下载, 这两个SDK包提供了OpenJDK所需的编译器以及Makefle中用到的外部命令。另外,还要准备一个6u14以上版本的JDK,因为OpenJDK的各个组成部分(Hotspot、JDK API、JAXWS、JX......有的是使用C++编写的,更多的代码则是使用Java自身实现的,因此编译这些Java代码需要用到-一个可用的JDK,官方称这个JDK为“Bootstrap JDK"。如果编译OpenJDK 7, Bootstrap JDK必须使用JDK6 Update 14或之后的版本,笔者选用的是JDK7 Update 4。最后需要下载-一个1.7.1 以上版本的Apache Ant,用于执行Java编译代码中的Ant脚本。对于Linux来说,所需要准备的依赖与Mac OS差不多,Bootstrap JDK和Ant都是- -样的,在MacOS中GCC编译器来源于XCodeSDK,而Ubuntu中GCC应该是默认安装好的,需要确保版本为4.3以上,如果没有找到GCC,安装binutils即可,在Ubuntu 10.10下编译OpenJDK 7u4所需的依赖可以使用以下命令- -次安装完成。
sudo apt-get install build-essential gawk m4 openjdk-6-jdk
1 ibasound2-dev libcups2-dev 1 ibxrender-dev xorg-dev xutils-dev
x11proto-print-dev binutils libmotif3 libmotif-dev ant

1.6.4进行编译
现在需要下载的编译环境和依赖项目都准备齐全了,最后我们还需要对系统的环境变量做一些简单设置以便编译能够顺利通过。OpenJDK在编译时读取的环境变量有很多,但大多都有默认值,必须设置的只有两个: LANG和ALT_ _BOOTDIR,前者是设定语言选项,必须设置为:

export LANG=C

否则,在编译结束前的验证阶段会出现一个HashTable内的空指针异常。另外一个ALT_BOOTDIR参数是前面提到的Bootstrap JDK,在Mac OS上笔者设为以下路径,其他操作系统读者对应调整即可。
export ALT_ BOOTDIR=/Library/Java/JavaVirtualMachines/jdk1.7.0 _04.jdk/Contents/ Home
另外,如果读者之前设置了JAVA_ HOME和CLASSPATH两个环境变量,在编译之前必须取消,否则在Makefile脚本中检查到有这两个变量存在,会有警告提示。
unset JAVA_ HOME
unset CLASSPATH
其他环境变量笔者就不再- -- 介绍了,代码清单1-1给出笔者自己常用的编译Shell脚本,读者可以参考变量注释中的内容。

                                        代码清单1-1环境变t设f
#语言选项,这个必须设置,否则编译好后会出现一个HashTable的NPE错
 

export LANG=C
#Bootstrap JDK的安装路径。必须设置
export ALT_BOOTDIR=/Library/Java/ JavaVirtualMachines/jdk1.7.0_04.jdk/Contents/
Home
普允许自动下载依赖
export ALLOW_DOWNLOADS=true
#并行编译的线程数,设置为和CPU内核数量一致即可
export HOTSPOT_BUILD_JOBS= 6
export ALT_PARALLEL_COMPILE_JOBS=6
#比较本次build出来的映像与先前版本的差异。这对我们来说没有意义,
#必须设置为false,否则sanity检查会报缺少先前版本JDK的映像的错误提示。
#如果已经设置dev或者DEV_ONLY=true,这个不显式设置也行
export SKIP_COMPARE_IMAGES=true
#使用预编译头文件,不加这个编译会更慢一些
export USE_PRECOMPILED_HEADER=true
#要编译的内容
export BUILD_LANGTOOLS=true
#export BUILD_JAXP= false .
#export BUILD_JAXWS=false
#export BUILD_CORBA= false :
export BUILD_HOTSPOT=true
export BUILD_JDK=true
#要编译的版本
#export SKIP_DEBUG_BUILD=false
#export SKIP_FASTDEBUG_BUILD=true
#export DEBUG_NAME=debug
#把它设置为false可以避开javaws和浏览器Java插件之类的部分的build .
BUILD_DEPLOY=false
#把它设置为false就不会build出安装包。因为安装包里有些奇怪的依赖,
#但即便不build出它也已经能得到完整的JDK映像,所以还是别build它好了
BUILD_INSTALL=false
#编译结果所存放的路径
export ALT_OUTPUTDIR=/Users/IcyEenix/Develop/JVM/jdkBuild/openjdk_7u4/build
#这两个环境变量必须去掉,不然会有很诡异的事情发生(我没有具体查过这些“诡异的#事情",Makefile脚本检查到有这2个变量就会提示警告)
unset JAVA_HOME
unset CLASSPATH
make 2>&1 | tee $ALT_OUTPUTDIR/build.1og

全部设置结束之后,可以输入make sanity来检查我们前面所做的设置是否全部正确。如果一切顺利,那公几秒钟之后会有类似代码清单1-2所示的输出。

代码清单卡2 make sanity检查

~/Develop/JVM/jdkBuild/openjdk_7u4$ make sanity
Build .Machine Information:
buird machine = IcyFenix-RMBP.1ocaF
Build Directory St ructure:
CWD = /Users/IcyFenix/Develop/JVM/jdkBuild/openjdk_7u4
TOPDIR = _.
LANGTOOES_TOPDIR = ./langtools
JAXP_TOPDIR = ./jaxp
JAXWS_TOPDIR = ./jaxws
CORBA_TOPDIR = -./corba
HOTSPOT_TOPDIR=./hotspat
JDK_TOPDIR = ./jdk
Build Directives:
BUILD_LANGTOOLS = true
BUILD_JAXP = true
-
-
BUILD_JAXWS = true
BUILD_CORBA = true
BUILD_HOTSPOT =true
DEBUG ELASSFILES =
DEBUG BINARIES =
....因篇幅关系,中间省略了大量的输出内.....
OpenJDK-specific settings:
FREETYPE HEADERS_PATH - /usr/X11R6/include
ALT_FREETYPE HEADERS_PATH =
FREETYPE LIB_PATH = /usr/X11R6/lib
ALT_FREETYPE_LIB_PATH =
Previous JDK Settings:
PREVIOUS RELEASE PATH = US ING-PREVIOUS_RELEASE_IMAGE
ALT_PREVIOUS_RELEASE_PATH =
PREVIOUS_JDK_VERSION = 1.6.0
ALT_PREVIOUS_JDK_VERSION =
PREVIOUS_JDK_FILE =
ALT_PREVIOUS_JDK_FILE =
PREVIOUS_JRE_FILE =
ALT_PREVIOUS_JRE_FILE =
PREVIOUS_RELEASE_IMAGE = /Library/Java/JavaVirtualMachines/jdk1.7.0_04.jdk/
Contents / Home
ALT_PREVIOUS_RELEASE_IMAGE =

Sanity check passed.
 Makefile的Sanity 检查过程输出了编译所需的所有环境变量,如果看到“Sanity check passed.",说明检查过程通过了,可以输人“make"执行整个OpenJDK编译( make不加参数,默认编译make all),笔者使用Core i7 3720QM/ 16GB RAM的MacBook机器,启动6条编译线程,全量编译整个OpenJDK大概需20分钟,编译结束后,将输出类似下面的日志清单所示内容。如果读者之前已经全量编译过,只修改了少量文件,增量编译可以在数十秒内完成。
#-- Build times ----------

Target all_ _product_ build
Start 2012-12-13 17:12:19
End
2012-12-13 17:31:07
00:01:19 corba
00:01: 15 hotspot
00:00:14 jaxp
00:7:21 jaxws
00:8:11 jdk
00:00:28 langtools
00:18:48 TOTAL


编译完成之后,进入OpenJDK源码下的buildj2sdk-image目录(或者build-debug. build-fastdebug这两个目录),这是整个JDK的完整编译结果,复制到JAVA_ HOME目录,就可以作为- -个完整的JDK使用,编译出来的虚拟机,在-version命令中带有用户的机器名。

> ./java -version
openjdk version "1.7.0- internal- fastdebug"
OpenJDK Runtime Envi ronment (build 1 .7.0-internal- fastdebug-
icyfenix_ 2012_ 12_ 24_ 15_ 57-b00)
OpenJDK 64-Bit Server VM (build 23.0-b21- fastdebug, mixed mode)

在大多数时候,如果我们并不关心JDK中HotSpot虚拟机以外的内容,只想单独编译
HotSpot虚拟机的话(例如调试虚拟机时,每次改动程序都执行整个OpenJDK的Makefile,
速度肯定受不了),那么使用hotspot/make目录下的Makefile进行替换即可,其他参数设
置与前面是一-致的,这时候虚拟机的输出结果存放在buildhotspot/outputdir/bsd_ amd64_
compiler2目录9中,进人后可以见到以下几个目录。

0 drwxr-xr-x  15  IcyFenix staff 510B 12 13 17:24 debug
0 drwxr-xr-x  15  IcyFenix staff 510B 12 13 17:24 fastdebug
0 drwxr-xr-x  15  IcyFenix staff 510B 12 13 17:25 generated
0 drwxr-xr-x  15  IcyFenix staff 510B 12 13 17:24 jvmg
0 drwxr-xr-x  15  IcyFenix staff 510B 12 13 17:24 optimi zed
0 drwxr-xr-x  584 IcyFenix staff 19K  12 13 17:25 product
0 drwxr-xr-x  15  IcyFenix staff 510B 12 13 17:24 profiled


这些目录对应了不同的优化级别,优化级别越高,性能自然就越好,但是输出代码与源码的差距就越大,难于调试,具体哪个目录有内容,取决于make命令后面的参数。在编译结束之后、运行虚拟机之前,还要手工编辑目录下的env.sh文件,这个文件
由编译脚本自动产生,用于设置虚拟机的环境变量,里面已经发布了“JAVA_ HOME、CLASSPATH、HOTSPOT_BUILD_ USER" 3个环境变量,还需要增加一个“LD_ LIBRARY_PATH",内容如下:

LD_LIBRARY_PATH=.:${JAVA_ HOME}/jre/lib/amd64/native_.threads:$ {JAVA_HOME}/jre/
1ib/amd64:
export LD_LIBRARY_PATH ;
然后执行以下命令启动虚拟机(这时的启动器名为gamma),输出版本号。
../env.sh
./gamma -version
Using java runtime at: /Library/Java/JavaVirtualMachines/jdk1.7.0_04.jdk/
Contents/Home/jre
java version "1.7.0_04"
Java (TM) SE Runtime Environment (build 1.7.0_04-b21)
OpenJDK 64-Bit Server VM (build 23.0-b21, mixed mode)在不同机器 上,最后一个目录名称会有所差别,bsd表示Mac oS系统(内核为FreeBSD) , amd64表示是
64位JDK (32位是x86),compiler2表示是Server VM (Client VM表示是compiler1) .
看到自己编译的虚拟机成功运行起来,很有成就感吧!

1.6.5 在IDE工具中进行源码调试
在阅读OpenJDK源码的过程中,经常需要运行、调试程序来帮助理解。我们现在已经可以编译出一个调试版本HotSpot虚拟机,禁用优化,并带有符号信息,这样就可以使用GDB来进行调试了。据笔者了解,许多对虚拟机了解比较深的开发人员确实就是直接使用GDB加VIM编辑器来开发、修改HotSpot的,不过相信大部分读者更倾向于在IDE环境而不是纯文本的GDB下阅读、跟踪HotSpot源码,因此这节就简单介绍一-下“如何在IDE中进行HotSpot源码调试"。首先,到NetBeans网站(http://netbeans.org/) 上 下载最新版的NetBeans,下 载时选择支持C/C++开发的那个版本。安装后,新建-一个项目,选择“基于现有源代码的C/C++项
目”,在源码文件夹中填入OpenJDK目录下hotspot目录的路径,在下面的单选按钮中选择“定制”,如图1-8所示,然后单击“下一步”按钮。

接着,在“指定构建代码的方法”中选择“使用现有的makefile",并填人Makefile文件的路径(在hotspot/make目录下),如图1-9所示。单击“下一步”按钮,将“构建命令”修改为以下内容: 

${MAKE} -f Makefile clean jvmg
ALT_ BOOTDIR=/Library/Java/JavaVirtualMachines/jdk1.7.0_ 04. jdk/ Contents/ Home
ARCH_ DATA_ MODEL=64 LANG=C

 

OpenJDK 7u4源码Makefile在终端运行时能正确获取到系统指令集架构为64位,但在NetBeans中却没有取得正确的值,误认为是32位,因此这里必须使用ARCH_ DATA_MODEE参数明确指定为64位。另外两个参数ALT_ _BOOTDIR和LANG的作用前面已经介绍过。单击“完成”按钮,HotSpot 项目就这样导人到NetBeans中了。不过,这时候HotSpot还运行不起来,因为NetBeans根本不知道编译出来的结果放在哪里、哪个程序是虚拟机的入口等,这些内容都需要明确告知NetBeans。在HotSpot工程上单击右键,
在弹出的快捷菜单中选择“属性”,在弹出的对话框中找到“运行”选项,设置运行命令为:

/Users/IcyFenix/Develop/JVM/jdkBuild/openjdK_7u4/hotspot/build/bsd/bsd_amd64_compiber2/ j-vmg-/gamna Queens

上面的Queens是MaKefile脚本自动产生的一段解八皇后问题的Java程序,用壬测试虚拟机,这里笔者直接拿来用了,读者完全可以将它替换为自己的Java程序。读者在调试Java代码执行时,如果要跟踪具体Java代码在虚拟机中是如何执行的,也许会觉得无从下手,因为目前在HotSpot主流的操作系统上,都采用模板解释器来执行字节码,它与HT编译器-样,最终执行的汇编代码都是运行期间产生的,无法直接设置断点,所以HotSpot增加了以下参数来方便开发人员调试解释器。

-XX: +TraceBytecodes - XX:StopInterpreterAt=<n>

这组参数的作用是当遇到序号为<n>的字节码指令时,便会中断程序执行,进人断点调试。在调试解释器部分代码时,把这两个参数加到gamma后面即可。最后,还需要在“环境”窗日中设置环境变量,也就是前面env.sh脚本所设置的那几个环境变量,如图1-10 所示。

完成以上配置之后,一个可修改、编译、调试的HotSpot工程就完全建立起来了,启动器的执行入口是java.c的main()方法,读者可以设置断点单步跟踪,如图1-11所示。

由于HotSpot的源码比较长,C/C++ 文件数量也很多,为了便于读者阅读,所以代码清单1-3给出了各个目录中代码的主要用途,供读者参考。 

 

 

 

1.7 本章小结
本章介绍了Java技术体系的过去、现在以及未来的一些发展趋势,并通过实战介绍了如何自己来独立编译-一个OpenJDK 7.作为全书的引言部分,本章建立了后文研究所必需的环境。在了解Java技术的来龙去脉后,后面章节将分为4部分去介绍Java在内存管理、Class文件结构与执行引擎、编译器优化及多线程并发方面的实现原理。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/576433.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《深入理解java虚拟机》第2章 Java内存区域与内存溢出异常

Java与C之间有一堵由内存动态分配和垃圾收集技术所围成的“高墙”&#xff0c;墙外面的人想进去&#xff0c;墙里面的人却想出来。 2.1 概述 https://blog.csdn.net/q5706503/article/details/84640762 对于从事C、C程序开发的开发人员来说&#xff0c;在内存管理领域&#…

线性表的定义和基本运算之线性结构

一、线性表的逻辑定义和性质 线性表是最简单和最常用的一种数据结构&#xff0c;他是由n个数据元素&#xff08;结点&#xff09;a1,a2,a3,a4........an组成的有限序列。其中&#xff0c;数据元素个数那位表的长度。当n为0时称为空表&#xff0c;非空的线性表通常记为 &#x…

数据结构之指针复习

废话不多说&#xff0c;拿起键盘就是干&#xff0c;直接上代码&#xff1a; #include <stdio.h>int main() {double *p;double x 66.6;p &x; //x占8个字节&#xff0c;一个字节占8位&#xff0c;一个字节一个地址double arr[3] { 1.1,2.2,3.3 };double *q;q &a…

数据结构之结构体复习

为什么出现结构体&#xff1f; 为了表示一些复杂的数据&#xff0c;一些基本数据类型无法满足要求&#xff0c; 当要用一个变量描述一个对象的多个属性时&#xff0c;普通的内置数据类型是表示不了的&#xff0c;这个时候就可以用结构体回。结构体和类很相似&#xff0c;唯一不…

高效管理读书笔记

高效管理读书笔记一、优秀的权威宣言二、主要的内容要点2.1 有权威的领导都会关心自己的员工2.2 问责而不指责2.3 多点尤达&#xff0c;少点超人三、原书一、优秀的权威宣言 优秀的权威就是&#xff1a; 指出大部分人视而不见的问题的气质今天畅所欲言而不是空等明天的好心【…

蒙特卡罗方法介绍(一)

蒙特卡罗方法介绍(一) 一、蒙特卡罗方法的基本思想和解题步骤 1.1 蒙特卡罗方法的基本思想 蒙特卡罗方法也称随机模拟法、随机抽样技术或统计实验发&#xff0c;其基本思想是&#xff1a;为了求解数学、物理、工程技术或生产管理等方面的问题。首先&#xff0c;建立一个与求…

神策数据张涛:如何让用户标签价值落地?

本文根据神策数据副总裁张涛在《用户个性化运营—标签体系搭建新机遇》主题沙龙中演讲整理所得。 标签系统&#xff0c;在企业中已不是什么“高大上”的说辞。然而让用户标签价值真正落地企业不多&#xff0c;就像“青少年谈性”&#xff0c; 有一段话形容得再贴切不过&#xf…

蒙特卡罗方法介绍( 二)

蒙特卡罗方法介绍( 二) 一、蒙特卡罗求解定积分 蒙特卡洛方法求解定积分有两种方法&#xff0c;一种是上一节中讲的投点法&#xff0c;另外一种是期望法&#xff08;也称平均值法&#xff09;。 1.1 投点法 给出如下曲线f(x)f(x)f(x),求f(x)f(x)f(x)在a,ba,ba,b上的积分&am…

大数据技术之kafka (第 3 章 Kafka 架构深入) 分区策略在分析

如果不懂分区策略请看我之前的文章&#xff1a;https://blog.csdn.net/ywl470812087/article/details/105328015 默认的方式我们采用的是Range策略方式&#xff08;按主题给消费者消费&#xff0c;主题被谁订阅了就谁消费&#xff09; 先看下下面这个图&#xff0c;画的很丑&a…

如何达成目标笔记

如何达成目标 一、本书主要内容 推荐序一 升级你的行动工具箱 推荐序二 人们可以改变 引言 成功者和自制力的悖论 //004 自制力到底是怎样的 //007 你能做什么 //009 本书的主题 //011 1.1 准备就绪 第1章 你明白自己去往哪里吗 别说“做到最好” //017 大局与细节 //…

大数据技术之 Kafka (第 4 章 Kafka API ) Producer API

4.1.1 消息发送流程 Kafka 的 Producer 发送消息采用的是异步发送的方式。在消息发送的过程中&#xff0c;涉及到了两个线程——main 线程和 Sender 线程&#xff0c;以及一个线程共享变量——RecordAccumulator。main 线程将消息发送给 RecordAccumulator&#xff0c;Sender…

《关键对话——何谓关键对话》读书笔记(一)

《关键对话——何谓关键对话》读书笔记&#xff08;一&#xff09; 利用假期的时间&#xff0c;将关键对话阅读了一遍&#xff0c;书中提到的观点&#xff0c;方法&#xff0c;场景等很适合我目前处的状态&#xff0c;有的时候读起来仿佛就是自己身临其境&#xff0c;有种感同身…

从java读取Excel继续说大道至简 .

在上一篇博客《从复杂到简单&#xff0c;大道至简》中说道我们要把复杂的问题简单化&#xff0c;也就是要把问题细分&#xff0c;让大问题变成小问题&#xff0c;这样解决起来会相对容易&#xff0c;当我们把容易的小问题解决掉了&#xff0c;大问题自动就会迎刃而解。 所以今天…

推荐算法工程师的成长之道

推荐算法工程师的成长之道 原创&#xff1a; gongyouliu 大数据与人工智能 3月20日 源链接&#xff1a;原文地址 本文&#xff0c;作者会基于自己的实践经验讲述推荐算法工程师的成长之道&#xff0c;这里的“道”有发展路径和道(道理、方法论、经验、智慧)两层意思。 所以本文…

java电子商务源码解读 b2b2c o2o

大型企业分布式互联网电子商务平台&#xff0c;推出PC微信APP云服务的云商平台系统&#xff0c;其中包括B2B、B2C、C2C、O2O、新零售、直播电商等子平台。 分布式、微服务、云架构电子商务平台 java b2b2c o2o 技术解决方案 开发语言&#xff1a; java、j2ee 数据库&#x…

信息流推荐多样性

信息流推荐多样性 一、问题现状 信息流产品中一个常见的问题是多样性越来越差&#xff0c;造成这种问题的原因在于机器学习算法本身。下面通过一副系统循环图来介绍多样性差的问题。 资讯库随机推荐文章&#xff0c;由于是按照全库比例采样&#xff0c;娱乐占比较大&#xf…

Robocode教程2——你的第一个robo,取个好名字哦

摘自&#xff1a;http://site.douban.com/widget/notes/7736245/note/210029011/ 你需要准备的东西&#xff1a;1.c语言的知识和一点点的java知识&#xff0c;robocode意在学习java&#xff0c;不要要太深的java水平&#xff0c;你只要理解java和c的区别就可以了。2.robocode A…

UI设计师的面试过程

Palantir Technologies是一家提供分析、整合、可视化各种数据的IT型技术公司。在该公司&#xff0c;前端工程师和后端工程师有同样的面试过程&#xff0c;前端工程师也需要的一定的编程基础。该公司技术博客Palantir TeckBlog日前发表了一篇博文《The UI Design Interview》&am…

数据在市场运营中的应用

数据在市场运营中的应用 1. 背景 目前的产品运营、用户拉新、渠道投放、留存等都是靠人工进行策略制定&#xff0c;有的公司和部门完全靠着以前的经验在尝试互联网产品的市场营销和运营。这样不仅效率很低&#xff0c;而且效果也不显著。 主要存在的问题有以下几点&#xff…