关于jdk:系统解析JDK源码领略大牛设计思想JAVA面试必备黄鹤之飞尚不得过

download:零碎解析JDK源码,领略大牛设计思维,JAVA面试必备黄鹤之飞尚不得过,猿猱欲度愁攀援。这是唐代著名诗人崔颢在长江边上观看黄鹤楼的现象所作的《黄鹤楼》一诗中的名句,表白了他对于黄鹤楼壮丽、高远、险恶的修建和自然风光的赞美,同时也反映出人们在面对壮阔的天然时所产生的有限敬畏之情。 黄鹤楼位于长江南岸的武汉市,是中国历史文化名城之一,也是中国三小名楼之一,与南京的秦淮河畔的“秦淮八艳”和浙江杭州的“平湖秋月”并称“江南三大名胜”。黄鹤楼的历史能够追溯到东晋时期,尔后几经兴废,现在的黄鹤楼是清末民初重建的,并在1957年被列为全国重点文物保护单位。 黄鹤楼之所以可能成为中国名楼之一,除了其背地的悠久历史和文化传承外,更因为它独特的地理位置和建筑风格。黄鹤楼坐落于长江南岸的壮丽山峰之间,建筑造型高大险恶,层层叠叠,气势磅礴。登上黄鹤楼,在楼顶远眺,能够看到长江两岸秀美的风景,感触到大自然的无穷魅力。 然而,崔颢所描述的“黄鹤之飞尚不得过”一句,却也体现出了黄鹤楼这样的壮观修建与天然之间的抵触和矛盾。黄鹤楼之所以如此雄伟、巍峨,正是因为其修建地位异样险要,这也给登楼者带来了很大的挑战和艰难。同时,因为修建地位的特殊性,黄鹤楼的颐养和修理也成为了一项微小的工程。 “猿猱欲度愁攀援”一句,则更加强调了人与大自然之间的反抗和矛盾。猿猱是一种灵便的动物,但即便是他们也有着攀登黄鹤楼的艰难和愁苦。这也提醒人们要尊重天然,珍惜大自然给予的所有资源和生态环境。 总之,崔颢的《黄鹤楼》一诗中的这两句名句,既表白了对于黄鹤楼壮美的风景的赞美,也体现了与天然的反抗和敬畏。在明天,咱们仍须要珍惜大自然,爱护生态环境,让天然呈现出最美妙的一面。

May 19, 2023 · 1 min · jiezi

关于jdk:从-JDK-9-到-19我们帮您提炼了和云原生场景有关的能力列表上

在 JDK 9 之前,Java 基本上均匀每三年出一个版本。然而自从 2017 年 9 月分推出 JDK9 到当初,Java 开始了疯狂更新的模式,基本上放弃了每年两个大版本的节奏。从 2017 年至今,曾经公布了 十一个版本到了 JDK 19。其中包含了两个 LTS 版本(JDK11 与 JDK17)。除了版本更新节奏显著放慢之外,JDK 也围绕着云原生场景的能力,推出并加强了一系列诸如容器内资源动静感知、无进展 GC(ZGC、Shenandoah)、原生的运维能力等等。这篇文章是 EDAS 团队的同学在服务客户的过程中,从云原生的角度将相干的性能进行整顿和提炼而来。心愿能和给大家一起意识一个新的 Java 状态。 云原生场景定义云原生的外在推动力之一是让咱们的业务工作负载最大化的利用云所带来的技术红利,云带来最大的技术红利就是通过弹性等相干技术,带来咱们资源的高效交付和利用,从而升高最终的资源的经济老本。所以如何最大化的利用资源的弹性能力是很多技术产品所谋求的其中一个指标。 残缺内容请点击下方链接查看: https://developer.aliyun.com/article/1156380?utm_content=g_10... 版权申明:本文内容由阿里云实名注册用户自发奉献,版权归原作者所有,阿里云开发者社区不领有其著作权,亦不承当相应法律责任。具体规定请查看《阿里云开发者社区用户服务协定》和《阿里云开发者社区知识产权爱护指引》。如果您发现本社区中有涉嫌剽窃的内容,填写侵权投诉表单进行举报,一经查实,本社区将立即删除涉嫌侵权内容。

May 17, 2023 · 1 min · jiezi

关于jdk:系统解析JDK源码深入理解Java编程语言

零碎解析JDK源码:深刻了解Java编程语言关键字:JDK源码、Java编程、零碎解析、深刻了解JDK是Java开发人员必备的开发工具包,其中蕴含了许多重要的类和接口,为Java编程提供了弱小的反对。然而,对于一些高级开发人员来说,仅仅应用JDK提供的API可能不够满足需要,他们须要深刻理解JDK源码来更好地了解Java编程语言的实质。本文将介绍如何零碎解析JDK源码,以便更深刻地把握Java编程语言。 一、筹备工作在开始解析JDK源码之前,咱们须要做一些筹备工作。首先,须要下载JDK源码,能够从Oracle官网上下载最新版本的JDK源码。其次,咱们须要抉择一款适宜本人的集成开发环境(IDE),例如Eclipse或IntelliJ IDEA等。最初,咱们还须要相熟一些根本的Java开发常识,例如Java反射、多线程等。 二、源码构造剖析JDK源码十分宏大,涵盖了许多外围模块和性能。因而,在开始解析源码之前,咱们须要理解JDK源码的整体构造和组织形式。在JDK源码目录中,次要蕴含以下几个子目录: 1src:蕴含了JDK外围类库的源代码,例如java.lang、java.util等。2test:蕴含了JDK测试用例的源代码,能够用于测试JDK代码的正确性和性能。3make:蕴含了JDK编译和构建脚本的源代码,能够用于生成JDK二进制文件。4doc:蕴含了JDK文档的源代码,能够用于生成JDK文档。5demo:蕴含了一些JDK示例程序的源代码,能够用于学习和演示JDK性能。通过对JDK源码的整体构造剖析,咱们能够更好地了解JDK代码的组织形式和依赖关系,从而更无效地进行源码解析。 三、源码解析办法在解析JDK源码时,咱们须要采纳一些无效的办法来提高效率和准确度。以下是几种罕用的源码解析办法: 1调试源码调试是最间接、最实用的源码解析办法之一。咱们能够通过IDE中的调试性能,逐渐执行JDK源码中的要害代码,从而深刻理解其外部实现和运行机制。这种办法非常适合对于一些简单、难以了解的代码段进行解析。 2浏览正文JDK源码中蕴含了大量的正文,这些正文不仅提供了代码的性能阐明和应用办法,还提供了一些代码实现的思路和细节。因而,浏览正文是解析JDK源码的重要办法之一。 3查看API文档在解析JDK源码时,咱们能够借助Java API文档来查找要害类和办法的定义和用法。这种办法尤其适宜对于一些罕用的API进行解析。 4参考书籍除了间接浏览JDK源码外,咱们还能够参考一些经典的Java编程书籍,例如《Java核心技术》、《Effective Java》等。这些书籍提供了深刻了解Java编程语言的思路和办法,对于学习和解析JDK源码十分有帮忙。 四、源码解析示例以下是一个简略的JDK源码解析示例,以java.lang.String类为例,介绍如何利用后面所述的源码解析办法进行源码解析。 1浏览正文:咱们能够通过浏览String类的正文来理解该类的作用和应用办法。例如,String类的正文中写道:“字符串是一个不可变的字符序列。字符串操作通常返回一个新的字符串,而不是批改原始字符串。”2查看API文档:咱们能够查看Java API文档中String类的定义和办法用法。例如,API文档中列出了String类的罕用办法,包含length()、charAt()、substring()等。3调试源码:咱们能够通过IDE的调试性能逐渐执行String类中的要害办法,从而深刻理解其外部实现和运行机制。例如,咱们能够在IDE中设置断点,并逐渐执行String类的构造函数和length()办法,察看变量的值和程序运行流程。4参考书籍:咱们能够参考《Java核心技术》等经典书籍,深刻了解String类的设计思路和实现办法。通过以上源码解析办法,咱们能够更好地了解JDK源码,进步Java编程的程度和能力。 五、总结零碎解析JDK源码是Java编程人员不可或缺的一项技能。通过把握JDK源码的构造和组织形式,以及采纳适当的源码解析办法,咱们能够更深刻地了解Java编程语言的实质和特点,进步本人的编程程度和能力。

May 13, 2023 · 1 min · jiezi

关于jdk:系统解析JDK源码领略大牛设计思想JAVA面试必备神化丹青即画图

download:零碎解析JDK源码,领略大牛设计思维,JAVA面试必备ChatGPT:开启人机交互新时代的AI语言模型 在现代科技疾速倒退的明天,人工智能曾经成为了一个备受关注的话题,而ChatGPT作为一种基于自然语言解决技术的AI语言模型,在人机交互方面扮演着越来越重要的角色。本文将介绍ChatGPT的基础知识、利用场景和将来瞻望等内容。 什么是ChatGPT?ChatGPT是由OpenAI研发的一种基于Transformer架构的大型AI语言模型,它能够实现自然语言生成和了解的工作,从而与人进行高度晦涩的对话。ChatGPT采纳了海量的训练数据和深度学习算法,从而能够一直地优化本身的预测和回复能力,让对话更加天然、灵便和人性化。 ChatGPT的利用场景ChatGPT在人机交互方面有着宽泛的利用场景,例如: 客服机器人:企业能够利用ChatGPT开发客服机器人,帮忙用户解答常见问题、提供服务反对等。智能助手:ChatGPT能够作为智能助手的核心技术,通过自然语言交互来实现日常事务、提供娱乐和学习等服务。语音辨认:ChatGPT能够与语音辨认技术联合,实现语音对话的性能,让人与机器之间的交互更加方便快捷。ChatGPT的将来瞻望随着人工智能技术的一直倒退,ChatGPT的利用前景也越来越广大。将来,咱们能够期待以下几个方面的倒退: 多语种反对:ChatGPT能够拓展到多种语言,让人们在寰球范畴内都可能应用它来进行自然语言交互。跨畛域利用:除了客服和娱乐畛域外,ChatGPT还能够拓展到医疗、金融、教育等各个领域,为人们提供更加全面的服务和反对。更加智能化:将来的ChatGPT将会领有更加智能的预测和回复能力,能够更好地了解人类的情感、语境和需要,让对话更加晦涩和天然。论断ChatGPT作为一种基于自然语言解决技术的AI语言模型,正在逐渐扭转人机交互的形式和状态。通过海量的训练数据和深度学习算法,ChatGPT能够实现高度晦涩、灵便和人性化的对话,为人们提供更加便当和高效的服务和反对。将来,咱们能够期待ChatGPT在多语种反对、跨畛域利用和智能化等方面的一直拓展和翻新。

May 12, 2023 · 1 min · jiezi

关于jdk:系统解析JDK源码领略大牛设计思想JAVA面试必备人生得意须尽欢

download:零碎解析JDK源码,领略大牛设计思维,JAVA面试必备毫无疑问,以后中国整体经济状态正在从传统经济向数字经济转型,千行百业也在减速数字化转型,特地是随着企业数据的积淀越来越宏大,对数据平台以及智能决策等新技术的需要也越来越旺盛。 国家公布的《“十四五”数字经济发展布局》中就强调:“有条件的大型企业要形成数据驱动的智能决策能力”;而科技部公布的《对于反对建设新一代人工智能示范利用场景的告诉》中,也明确使用优化决策等技术,实现生产过程等领域的智能决策。 可能看到,过来几年受疫情的冲击,企业抗危险能力、生产供应柔性、精密化经营等话题被晋升到前所未有的高度,这让企业的数字化转型更加迫切,因此要疾速的适应市场变动,就需要善用数据,让决策智能等新技术在企业的商业模式中创造出更大的价值,更好地升高未来挑战对企业造成的“不必定”的影响,由此才能在激烈的竞争中立于“不败之地”。 而作为寰球最大的企业级软件公司,以及将“数据”融入到公司“基因”和“血脉”中的甲骨文,在此过程中也通过继续的技术创新,打造了“双引擎”——即数据库和云,并且将二者实现了“融会贯通”,由此不只能够驱动更多的企业更好的拥抱决策智能,同时也能够减速泛滥企业的数字化转型步调。 正如甲骨文公司副总裁及中国区技术平台总经理吴承杨所言:“当明天数据越来越重要,在AI和ML变成寰球最热门话题的大背景下,甲骨文公司具备‘算力、数据、模型和生态’等劣势,这也让甲骨文可能帮助泛滥中国的企业在使用数据库,包含基于数据做决策的时候能够足够简略,开箱即用,未来咱们也心愿通过‘双引擎’技术的继续翻新,让千行百业能够更便当地通过数据创造出更多的新价值。 数据驱动决策大势所趋 家喻户晓,企业的数字化转型从来不是一个简略的技术问题,其目标或者本质是要将数字化的思维和方法贯穿到企业的要害场景之中,包含生产、销售、营销、服务等方面,而背地的要害就在于企业要构建数据驱动的模式,由此才能推动企业实现全面的数字化转型。 特地是随着大数据、人工智能、决策智能等技术融合日益加深,通过数据驱动打造企业智能化和精密化的经营模式已成为要害力量。从甲骨文近期公布的《寰球决策困境研究报告》中,咱们就能充分感受到这种变动,该报告对包含中国在内的17个国家/地区的14000多名员工和企业负责人开展调研,得出的论断是——做出正确决策至关重要,但非易事。 一是,数据的爆发式增长,正在阻碍企业的取得胜利。报告浮现,81%的中国受访者认为,他们正受到来自更多渠道的数据“轰炸”,这比以往任何时候都要多;超过86%的中国受访者示意,宏大的数据量使得集体和工作决策变得更加简单;更有高达90%的中国受访者示意,与日俱增的数据起源,正在有碍企业或者组织获得胜利,原因在于需要其余资源来收集所有数据,并确保在此过程中不能丢失任何数据;极大的减少了收集数据的工夫,并造成战略决策迟缓,且减少出错的机会。 二是,越来越多的企业受到了基于数据决策带来的干扰。报告指出,有76%的中国受访者示意,他们每天所做的决策数量在过来三年的工夫里减少了10倍,也有同时超过78%的中国受访者示意,因数据量过于宏大而放弃做出决策,有82%的中国企业指导者更是承认,他们对数据不足信赖,由此导致残缺无奈做出任何决策;超过92%的中国企业指导者正在蒙受决策干扰,不少指导者对过来一年所做的决策也曾感到后悔、内疚或已经质疑过自己做出的决策。 三是,利用技术创新实现数据驱动型决策的公司将是未来的趋势所在。报告中提到,有96%的中国企业指导者认为,具备合适的决策智能可能决定组织的胜利与否,背地的关键在于越来越多的指导者意识到,正确的数据和洞察可能帮助企业改恶人力资源、供应链、财务和客户体验方面的决策,同时还能在其余方面获得胜利,包含超过81%的中国受访者认为,数据驱动决策可能更好地排汇人才;78%的受访者认为,可能更好地获得投资者的青睐;而更有超过90%的中国企业指导者示意,在未来偏向于让机器人做出决策。 对此,甲骨文公司高级副总裁及亚洲区董事总经理李翰璋强调:“随着数字经济的飞速发展,企业需要更多的相干数据来获得全局视图。同时,对于负责制订决策的企业指导者而言,如果忽视这些数据背地的价值,就需自担风险。因此,企业指导者是时候重新考虑对待数据和决策的方法了。” 由此可见,在数据大爆炸的明天,对于企业而言要基于数据做出正确的决策绝不是一件容易的事件,日益减少的数据对企业而言诚然是一笔“宝藏”资源,但要真正要让数据产生价值,驱动企业做出高质量的决策,要害的“落脚点”还在于企业需要将信息、数据、洞察及口头串联起来,由此才能开释数据带来的全新价值。 减速企业拥抱决策智能 在此背景下,甲骨文基于自身在数据领域四十多年的积累和积淀,并以全新的“双引擎”技术创新形式,为企业提供收集、分析和利用数据所需的决策智能,助力企业做出现实的决策。 甲骨文公司中国区技术咨询部高级总监李珈示意:“产生决策智能的要害因素,不能仅仅只靠一种技术能够实现的。这是一门实践,需要通过技术来撑持零碎不断地练习,去理解数据,收集数据,并对这些数据进行分析,进行挖掘,而后不断根据后果去反馈,去调优,去锤炼模型,再去修改这个模型。这是一个改善决策智能的要害因素的过程,也是甲骨文心愿通过数据驱动企业决策背地所保持的逻辑。”基于此,甲骨文也正通过“双引擎”的技术创新形式,驱动和减速更多企业拥抱决策智能。 首先,甲骨文能够通过“融合数据库”的形式,让企业的数据平台能够反对所有数据类型、工作负载,以及不同的开发风格。 例如,在工作负载方面,甲骨文可能提供HTAP混合事务和分析处理能力,而这个功能 十年前甲骨文就已经推出了,发展到明天功能已经十分弱小,最为典型的如 Oracle Database In-Memory就能撑持不同的利用;此外,甲骨文也能够对不同数据类型提供反对,如关系、文档、图和空间多模数据处理。 更为要害的是,甲骨文往年刚刚公布的Oracle Database 23c 开发者版本,新减少了“JSON Relational Duality”功能,该功能不只能够让开发人员可能根据不同的使用场景抉择合适的拜访格局,而无需担心数据结构、数据映射、数据一致性或性能优化方面的问题,同时还可能基于关系数据和JSON 数据运行图形分析。也正因此,第三方分析机构IDC给与了这项功能极高的评估,指出:“Oracle JSON Relational Duality 是一个真正的革命性解决打算,可能是信息科学领域近20 年来非常重要的翻新之一。” 其次,借助甲骨文弱小的云基础设施(OCI)能力,明天企业无论是在云端还是本地的数据中心,同样也能获得雷同的“自治数据库”能力。 简略来说,过来甲骨文的自治数据库只能运行在Oracle私有云环境之中,对于很多想尝试自治数据库的企业来说是有一些难度的,但现在甲骨文买通了云端和本地的数据中心,由此让“自治数据库”的能力变得“无处不在”。 这其中翻新的“代表”就是Oracle Exadata专有云数据库一体机(Oracle Exadata Cloud@Customer,ExaCC),它既能为企业提供原有的利用数据库撑持;同时另一方面它也能以低成本、便当自助的形式帮助企业轻松部署甲骨文自治数据库。换句话说,基于ExaCC运行的多虚拟机自治数据库能够更好地利用Oracle Exadata基础设施“底座”的性能、可扩展性和可用性劣势,这样就可能让企业更加轻松部署云原生和要害工作数据库。不只如此,过来几年甲骨文还推出了很多的翻新打算,如Oracle专有云本地化解决打算(Oracle Dedicated Region Cloud@Customer),该打算可能将私有云的能力全副“搬到”客户的本地数据中心等等。 最初,甲骨文还提供Oracle 分析平台(Oracle Analytics platform),借助其内置的机器学习技术,也可能帮助企业更快实现数据分析。“Oracle Analytics的技术门槛非常低,企业可能开箱即用,而根本不需要知道它是用什么方法,什么原理帮助企业实现数据分析过程的。”李珈说。 不难看出,通过甲骨文在弱小的“融合数据库”、无处不在的“自治数据库”,以及数据库中内嵌的机器学习和人工智能,企业可能更好的在基础数据管理、增强和利用分析方面“大展身手”,更快地拥抱决策智能,让决策智能的获得变得更加简略和便利。 “双引擎”赋能千行百业 事实上,甲骨文“双引擎”的技术创新形式在决策智能领域的利用仅仅是一个“缩影”,在更大范畴,更多利用场景中,甲骨文的“双引擎”也在赋能千行百业的数字化转型。 吴承杨说:“如果说明天甲骨文和过来五年或者十年有什么不一样,最大的变动就在于咱们新增了云的引擎,这不只推动了甲骨文的业务的高速增长,更重要的是也让甲骨文成为了一家云转型胜利的公司。” 的确如此,甲骨文2023财年第三季度财报浮现,其寰球总营收为124亿美圆,若按固定汇率计算,同比增长21%;其中云服务营收到达41亿美圆,若按固定汇率计算,同比增长48%;此外,甲骨文云基础设施中的laaS业务营收为12亿美圆,若按固定汇率计算,同比增长57%。截止目前,甲骨文OCI在寰球范畴内已经部署了超过41个云区域。 因此,这也让扎根中国市场34年的甲骨文,在全新的期间能够以“双引擎”的技术创新能力,将更多先进的科技带给中国企业;同时也在保证数据安全合规的同时,能够以更低成本,更疾速部署的劣势助力千行百业减速数字化转型。 第一,从数据翻新维度看,甲骨文是寰球多数具备“算力、数据、模型和生态”等劣势的公司,因此无论是数据的治理,还是基于数据做决策智能,都是甲骨文可能施展价值的领域。 例如,在算力方面,甲骨文 OCI 在寰球具备超过41个云区域,同时具备弱小的GPU算力劣势;在数据方面,甲骨文已经做了45年的工夫,可能说甲骨文是最懂在行业中如何做数据的;在模型方面,甲骨文深耕企业级市场,做的是数据相干的大模型,自治数据库就是其中的‘集大成者’;而在生态方面,甲骨文不只是数据库公司,也是寰球最大的企业级软件公司,更是唯一一家提供完整企业级IaaS、PaaS和SaaS产品与服务的云厂商,特地是在ERP还是HCM乃至垂直行业软件方面,甲骨文都有深入布局,因此可能将企业在不同利用中的数据发掘出来,通过融合数据库弱小的能力,更好地开释数据价值进去。 第二,从企业赋能维度看,国家此前提出了“双循环”的策略,越来越多各赛道的中国企业也正在将中国的业务和翻新模式输入到海内市场,心愿寻找到更多新的商业机会,而在此过程中甲骨文也可能提供更好的私有云服务,助力企业更好的“入华出海”。 “明天越来越多的中国企业在出海的时候抉择甲骨文,这一点也印证了甲骨文在私有云上的翻新能力赢得了客户的认可,因此这也让咱们在中国私有云市场的发展速度远超寰球市场,同时也甲骨文在未来更加有自信心地服务好好中国的本地客户,同时帮助海内的客户进入到中国,比如HSBC(汇丰银行)进入中国市场时,甲骨文就是残缺满足安全合规的申请情况帮助他们实现了落地。”吴承杨说。 第三,从心态凋谢的维度看,可能看到过来几年中国市场出现了越来越多的数据库公司,对此甲骨文也是始终保持凋谢和互相学习的态度,并心愿通过自身的技术的翻新,让更多的企业意识到数据的后劲,开释好数据的价值。 对此,吴承杨示意:“咱们非常欢迎数据库这个行业有更多的厂商进入,不管在寰球还是在中国,这是非常明确的,因为甲骨文认为数据库其实是一个绝对冷门的领域,需要更多人关注,因为关注数据库就是关注数据。因此甲骨文鼓励更多的厂商投入这个领域,咱们也违心保持着凋谢的心态和同行互相学习,同时也违心把选择权交给客户做决定。” “回头来看,甲骨文在数据库领域已经做了超过45年的工夫,咱们每年研发投入在营收的15%左右,每年有超过60亿美圆用来研发,同时寰球也具备很多的客户,每年也会做大量的迭代和优化,最终的目标和愿景也很清晰——就是让数据库‘化繁为简’,简略到让企业感觉不到它的存在,简略到人人都可能使用。”吴承杨最初说。 全文总结,“数字中国”的顶层布局、中国式现代化的整体规划为整个科技产业创造了巨大的历史时机,愈减速了千行百业数字化转型的步调,而扎根中国市场34年的甲骨文,也正通过全新的“双引擎”技术创新和赋能的形式,减速中国企业数字化转型,推动中国数字经济的高质量发展,这不只是甲骨文“以行践言”推动中国企业更快拥抱决策智能,最大化开释数据价值的体现,同时也是其过来三十多年来能够深度融入中国市场,并服务好中国行业客户的核心和关键所在。

May 7, 2023 · 1 min · jiezi

关于jdk:系统解析JDK源码领略大牛设计思想JAVA面试必备完结

JDK(Java Development Kit)是一个全套的Java开发工具集,由Java编译器、JVM以及其余Java开发工具组成。本文将介绍零碎解析JDK的过程。 download:https://www.666xit.com/3972/ 下载JDK首先须要从官方网站下载JDK安装包,依据不同操作零碎抉择对应的版本,比方Windows、Linux或者MacOS等。 装置JDK下载实现后,双击运行安装程序,并依照提醒进行装置。装置结束后,能够在电脑中找到JDK所在目录,个别状况下默认装置在C盘的Program Files目录下。 配置环境变量为了让零碎可能正确地解析JDK,须要配置相应的环境变量。在Windows零碎中,须要在“控制面板”->“零碎”->“高级零碎设置”->“环境变量”中增加JAVA_HOME和Path两个变量。JAVA_HOME变量指向JDK的装置门路,Path变量则须要将JDK的bin目录增加到其中。 解析JDK当以上步骤实现之后,零碎就能够正确地解析JDK了。接下来能够应用JDK提供的各种工具进行Java开发,比方Java编译器(javac)、Java虚拟机(java)、Java文档生成器(javadoc)等等。 总结:对于Java开发人员而言,JDK是必不可少的工具集。通过下载、装置和配置环境变量,能够让零碎正确地解析JDK,从而能够进行各种Java开发工作。

May 6, 2023 · 1 min · jiezi

关于jdk:深入了解JDK源码系统解析

深刻理解JDK源码:零碎解析关键字:JDK源码、解析、深刻理解、系统分析在Java开发中,JDK源码是咱们必不可少的工具。然而,对于大多数开发人员来说,JDK源码还是一片神秘的畛域。如果你想真正了解JDK源码,那么你须要深刻系统地解析它。本文将介绍如何通过系统分析JDK源码来深刻理解它。 为什么要解析JDK源码?首先,JDK源码是Java开发人员必备的工具之一。当咱们遇到问题时,通过查看源码能够更好地了解和解决问题。其次,深刻理解JDK源码能够让咱们更好地把握Java的外部机制。这有助于咱们写出更高质量的代码,进步应用程序的性能和稳定性。 如何系统分析JDK源码?装置JDK源码首先,你须要下载JDK源码。你能够从Oracle官方网站下载JDK源码包。下载实现后,你须要将源码包解压缩到一个目录下。 抉择适合的开发工具你须要抉择一个适合的开发工具来剖析JDK源码。罕用的开发工具包含Eclipse、IntelliJ IDEA和NetBeans等。这里以Eclipse为例。 导入源码在Eclipse中,你能够通过以下步骤导入JDK源码: 抉择File -> New -> Java Project 输出项目名称并勾选"Use an execution environment JRE"选项,并抉择你应用的JRE版本 点击Next,而后点击"Add External JARs"按钮,抉择你下载并解压的JDK源码目录下的src.zip文件 点击Finish,Eclipse将主动导入JDK源码 调试源码当你胜利导入JDK源码后,你能够通过调试来深入分析它。你能够设置断点、单步执行代码、查看变量值等。通过调试,你能够更好地了解JDK源码的工作流程和外部机制。 总结JDK源码是Java开发人员必不可少的工具之一。通过零碎解析JDK源码,咱们能够更好地了解和解决问题,同时也可能把握Java的外部机制,写出更高质量的代码。本文介绍了如何通过装置、抉择适合的开发工具、导入源码和调试源码等步骤来零碎解析JDK源码。

May 6, 2023 · 1 min · jiezi

关于jdk:更高水准的供应链安全实践Alibaba-Dragonwell-及其-SLSA-2-级认证

01 前言计算机科学史上涌了 C/C++、Java、JavaScript、Ruby、Python、Perl 等多种编程语言。每一种语言都有其善于的畛域,其中Java语言凭借其面向对象、主动内存治理、多线程性能优越等劣势继续处于浪潮之巅。目前市场上存在着大量品质不错 OpenJDK 的衍生版本可供用户抉择。它们或者性能卓越,或者针对某些场景做出了优化。但 JDK 作为根底软件,归根结底软件的可信赖和可用性是最咱们最根底的谋求。 02 Alibaba DragonwellAlibaba Dragonwell,一款收费的、生产就绪型的 OpenJDK 发行版。阿里巴巴提供长期反对,包含性能加强和平安修复。不同于以往的 OpenJDK。Alibaba Dragonwell 有其特有的五大劣势: 2.1 平安与稳固Alibaba Dragonwell 与 OpenJDK 社区放弃严密单干,始终保持对社区工作的跟踪,及时同步上游更新,以保障 Java 利用的平安和稳固。 2.2 性能与效率Alibaba Dragonwell 的前身是阿里巴巴外部应用的 AJDK。AJDK 作为阿里巴巴 Java 利用的基石,撑持了阿里简直所有的 Java 业务,积攒了大量业务场景下验证过的新技术,这些新技术极大得进步了阿里巴巴Java业务的性能和故障排查效率。AJDK 翻新技术,会逐渐奉献到 Dragonwell 积淀。 2.3 Java SE 规范兼容Alibaba Dragonwell Standard Edition 齐全遵循 Java SE 规范。 2.4 特色性能Alibaba Dragonwell Extended Edition还具备诸多特色性能,例如 JWarmup、ElasticHeap 等等。这些个性在阿里巴巴外部失去了广泛应用,解决了很多生产实践中的痛点,为阿里巴巴 Java 业务的稳固运行立下了汗马功劳,能够说是 Alibaba Dragonwell 的独门武器。 2.5 新技术的疾速采纳基于阿里工程实际,Alibaba Dragonwell 会抉择移植高版本 Java 的重要性能,这些移植性能曾经在阿里外部被大规模部署,用户都能够收费应用,而不必等 OpenJDK 下一个 LTS 版。 ...

April 26, 2023 · 2 min · jiezi

关于jdk:JDK20正式发布了GA版本短期维护支持以及JDK21预览

最近,Oracle公布了JDK20,相比对于Java开发者来说,JDK的发版是比拟收关注的事件了,小简也来和大家一起理解理解JDK20产生了什么变动呢? 首先,JDK20是一个短周期版本,有6个月的保护工夫,据开发者打算,下一个LTS也就长期保护版本将会在2023年9月份公布到来,也就是JDK21了。 目前JDK21也是推出了晚期预览版本。 JDK 20 提供了来自 OpenJDK 我的项目 Amber 的语言改良(Switch 的记录模式和模式匹配),OpenJDK巴拿马我的项目的加强性能,以互连Java虚拟机(JVM)和本机代码(内部函数和内存API和矢量API),以及与 Project Loom 相干的性能(作用域值、虚构线程和结构化并发),这些性能将大大简化编写、保护和察看高吞吐量并发应用程序的过程。 Oracle 通过可预测的公布打算每六个月公布一次新的 Java 性能。这种节奏提供了源源不断的翻新,同时不断改进平台的性能、稳定性和安全性,有助于进步 Java 在各种规模的组织和行业中的普遍性。变动Language Updates and Improvements JEP 432: Record Patterns (Second Preview): Enhances the Java language by allowing users to nest record patterns and type patterns to create a powerful, declarative, and composable form of data navigation and processing. This helps increase developer productivity by enabling them to extend pattern matching to allow for more sophisticated and composable data queries.JEP 433: Pattern Matching for Switch (Fourth Preview): By extending pattern matching to switch, an expression can be tested against a number of patterns—each with a specific action—so that complex data-oriented queries can be expressed concisely and safely. Expanding the expressiveness and applicability of switch expressions and statements helps increase developer productivity.Project Loom Preview/Incubator Features ...

March 23, 2023 · 3 min · jiezi

关于jdk:请你喝一杯-Corretto谈一谈-JDK-的新选择

前言如果以20年的工夫为限,让咱们选出一个影响力最大的程序语言,我的答案应该只有一个 – 那就是 Java。这个1995年诞生的全新的计算机语言,以“一次编写,到处运行”的跨平台个性以及面向对象、泛型编程等古代语言的个性迅速成为了企业级利用乃至挪动利用开发的首选。 亚马逊云科技开发者社区为开发者们提供寰球的开发技术资源。这里有技术文档、开发案例、技术专栏、培训视频、流动与比赛等。帮忙中国开发者对接世界最前沿技术,观点,和我的项目,并将中国优良开发者或技术举荐给寰球云社区。如果你还没有关注/珍藏,看到这里请肯定不要匆匆划过,点这里让它成为你的技术宝库!随同着 Java 的遍及,用以开发并提供 JVM 反对的 Java Development Kit (JDK) 就成为了最重要的一个开发工具包。历史上已经呈现过许多 JDK 的发行版,例如 IceTea、Blackdown、JRockit、Apache Harmony 等等至今都已成为历史。 Java 是寰球利用最宽泛的语言技术栈。据统计,寰球 Java 开发工程师超过1000万名。而 JDK 作为 Java 语言的软件开发工具包,是整个 Java 利用的外围。以后,在 JDK 寰球市场份额中,Oracle JDK 占 70%、OpenJDK 约占 21%。但2019年1月之后,Oracle 不再提供 Oracle JDK 8 收费商业版本更新。 Amazon Corretto 是凋谢 Java 开发工具包 (OpenJDK) 的收费、多平台、生产就绪型发行版。Corretto 提供长期反对,其中包含性能加强和平安修复。亚马逊在外部的数千种生产服务上运行 Corretto,并且 Corretto 已被证实可能兼容 Java SE 规范。借助 Corretto,您能够在罕用操作系统(包含 Linux、Windows 和 macOS)上开发和运行 Java 应用程序。 明天,当咱们面对 OpenJDK、Azul、Oracle Java SE 等许多 JDK 的选项的时候,咱们又该如何取舍呢? 什么是 Amazon Corretto ?咖啡爱好者都晓得,Correto 是一种意大利稀释咖啡掺入相似白兰地的烈酒和谐而成的咖啡。抿上一口,酒与咖啡共饮带来的刺激口感和浓烈氛围使人陶醉。 ...

March 2, 2023 · 3 min · jiezi

关于jdk:从-JDK-9-到-19我们帮您提炼了和云原生场景有关的能力列表上

在 JDK 9 之前,Java 基本上均匀每三年出一个版本。然而自从 2017 年 9 月分推出 JDK9 到当初,Java 开始了疯狂更新的模式,基本上放弃了每年两个大版本的节奏。从 2017 年至今,曾经公布了 十一个版本到了 JDK 19。其中包含了两个 LTS 版本(JDK11 与 JDK17)。除了版本更新节奏显著放慢之外,JDK 也围绕着云原生场景的能力,推出并加强了一系列诸如容器内资源动静感知、无进展 GC(ZGC、Shenandoah)、原生的运维能力等等。这篇文章是 EDAS 团队的同学在服务客户的过程中,从云原生的角度将相干的性能进行整顿和提炼而来。心愿能和给大家一起意识一个新的 Java 状态。 云原生场景定义云原生的外在推动力之一是让咱们的业务工作负载最大化的利用云所带来的技术红利,云带来最大的技术红利就是通过弹性等相干技术,带来咱们资源的高效交付和利用,从而升高最终的资源的经济老本。所以如何最大化的利用资源的弹性能力是很多技术产品所谋求的其中一个指标 同时,另外一个外在推动力是如何去防止云厂商技术的锁定,实现伎俩就是推动各个领域的规范的建设。自从云原生诞生以来, 随着 Kubernetes 的大获胜利,以开源为次要状态的技术产品,继续从各个领域中造成既定的标准和规范,是技术产品谋求的另外一个指标。 有了最终的指标,通过一直优化的规范,那么如何在这个新场景下利用上相干的规范能力,是很多产品一直往前演进的方向。以上两点,咱们本人的产品如此,Java 亦如此。 Java 针对性能力针对 Java 的近十个版本更新,咱们将从运维、编程模型与运行时、内存三个场景进行解读。其中运维局部次要是如何利用现有的容器技术获取运维指标以及在这个场景下的一些原生能力的反对。同时 Java 也在字符串和新的 IO 模型与能力。另外一个最大的变动来自于内存局部,除了在容器场景下对于 CGroup 有更好的反对之外,还提供了令人期待的 ZGC 和 Shenandoah GC 两款无进展的垃圾回收器,除了提供低时延的 STW 之外,还具备偿还局部内存给操作系统,最大限度的提供了利用在云原生场景下利用硬件资源的能力。 整个解读分为高低两篇,除了内存会应用一个独自的文章进行解读之外,剩下的内容次要在这章解说。更原生的运维场景1 OperatingSystemMXBean容器的其中一个能力是过程级别的隔离,默认状况下,容器内的 Java 程序如果基于 JMX 中提供的 OperatingSystemMXBean 中的办法进行拜访,会返回所在宿主机的所有资源数据。在 JDK 14 的版本之后,在容器或其余虚拟化操作环境中执行时,OperatingSystemMXBean 办法将返回容器特定信息(如:零碎可用内存、Swap 、Cpu、Load 等),这项能力在基于 JMX 开发的很多能力(如:监控、零碎限流等)是一一项特地敌对的能力。JDK 14 中波及到的革新的 API 如下: ...

February 17, 2023 · 3 min · jiezi

关于jdk:一种面向业务配置基于JSF广播定时生效的工具

作者:京东物流 王北永 姚再毅 李振 1 背景目前,ducc实现了实时近乎所有配置动静失效的场景,然而配置是否实时失效,不能直观展现每个机器上jvm内对象对应的参数是否已变更为精确的值,大部分时候须要查看日志确认是否失效。 2 技术依赖1)Jsf:京东RPC框架,用作机器之间的通信工具 2)redis/redisson:redis,用作配置信息的存储 3)ZK/Curator: Zookeeper,用作配置信息的存储 和redis二选一 3)clover:定时工作集群,用作工作提早或周期性执行 3 实现原理1)接入方: 各个接入零碎通过接入治理模块获取token,并指定所在零碎公布的的服务器ip,用作后续的ip鉴权。当系统启动时,主动在各个系统生成接口提供方,并注册到JSF注册核心。别名需各个系统惟一不反复。鉴权为对立服务端做IP鉴权。 2)对立配置服务端: 提供按不同接入方、不同零碎、不同环境的配置界面。业务人员可设定主动失效工夫或者立刻失效工夫。如果是立即失效,则通过JSF播送或者指定机器失效配置。如果是定时失效,则新增定时器并指定失效规定,达到工夫后触发播送告诉。 整个接入方和对立配置服务端的架构如下图 4 实现步骤1)重写JSF类ConsumerConfig类办法refer,将其中的轮训调用客户端改为播送调用客户端BroadCastClient。 this.client= new BroadCastClient(this);this.proxyInvoker = new ClientProxyInvoker(this);ProtocolFactory.check(Constants.ProtocolType.valueOf(this.getProtocol()), Constants.CodecType.valueOf(this.getSerialization()));this.proxyIns = (T) ProxyFactory.buildProxy(this.getProxy(), this.getProxyClass(), this.proxyInvoker);2)播送调用客户端办法别离获取以后注册核心有心跳的服务提供者和已失去连贯的机器列表。对对立配置来讲,要么同时失败,要么同时胜利,判断如果存在不失常的服务提供方,则不同步。只有全副提供方存在才能够开始播送配置信息 ConcurrentHashMap<Provider, ClientTransport> concurrentHashMap = this.connectionHolder.getAliveConnections(); ConcurrentHashMap<Provider, ClientTransportConfig> deadConcurrentHashMap = this.connectionHolder.getDeadConnections(); if(deadConcurrentHashMap!=null && deadConcurrentHashMap.size()>0){ log.warn("以后别名{}存在不失常服务提供方数量{},请关注!",msg.getAlias(),deadConcurrentHashMap.size()); throw new RpcException(String.format("以后别名%s存在不失常服务提供方数量%s,请关注!",msg.getAlias(),deadConcurrentHashMap.size())); } if(concurrentHashMap.isEmpty()){ log.info("以后别名{}不存在失常服务提供方",msg.getAlias()); throw new RpcException(String.format("以后别名%s不存在失常服务提供方",msg.getAlias())); } Iterator aliveConnections = concurrentHashMap.entrySet().iterator(); log.info("以后别名{}存在失常服务提供方数量{}",msg.getAlias(),concurrentHashMap.size()); while (aliveConnections.hasNext()) { Entry<Provider, ClientTransport> entry = (Entry) aliveConnections.next(); Provider provider = (Provider) entry.getKey(); log.info("以后连贯ip={}、port={}、datacenterCode={}",provider.getIp(),provider.getPort(),provider.getDatacenterCode()); ClientTransport connection = (ClientTransport) entry.getValue(); if (connection != null && connection.isOpen()) { try { result = super.sendMsg0(new Connection(provider, connection), msg); } catch (RpcException rpc) { exception = rpc; log.warn(rpc.getMessage(), rpc); } catch (Throwable e) { exception = new RpcException(e.getMessage(), e); log.warn(e.getMessage(), e); } } }3)服务配置端,当业务人员配置及时失效或者工作达到时,则依据配置,生成服务调用方,通过对立刷新接口将配置同步刷新到对应的接入零碎中,如下图为操作界面,当增删改查时,会将属性增量同步。 ...

January 19, 2023 · 2 min · jiezi

关于jdk:Linux系统安装jdk

JDK是 Java 语言的软件开发工具包,次要用于挪动设施、嵌入式设施上的java应用程序。JDK是整个java开发的外围,它蕴含了JAVA的运行环境,JAVA工具和JAVA根底的类库。 我的环境是租的小品牌服务器,他们价格比拟便宜,不便做一些试验 1、到jdk的官网下载安装包https://developers.redhat.com... 2、下载好后上传的零碎中 3、解压安装包并指定目录 tar zxvf jdk-8u91-linux-x64.tar.gz -C /opt 4、挪动文件并批改文件名mv jdk1.8.0_91/ /usr/local/java 5、批改配置文件,设置变量 cd /etc/profile.d/vi java.shexport JAVA_HOME=/usr/local/java //设置Java根目录//export PATH=$PATH:$JAVA_HOME/bin //在PATH环境变量中增加Java根目录下的bin/子目录//source java.sh //java.sh脚本导入到环境变量,使其失效// 6、查看Java的版本java -version 7、写一段Java的小脚本测试 vi abc.javapublic class abc { public static void main (String[] args) { System.out.println("你好,世界!!!"); }} 编译javac abc.java 测试 这样的话就阐明你的jdk环境曾经搭建好了,

August 3, 2022 · 1 min · jiezi

关于jdk:JDK-8-Stream-数据流效率怎么样

stream 的操作品种①两头操作②终端操作stream 的特点①只能遍历一次:②采纳外部迭代的形式:stream 绝对于 Collection 的长处stream 和 iterator 迭代的效率比拟低1. 映射解决测试2. 过滤解决测试3. 天然排序测试4. 归约统计测试5. 字符串拼接测试6. 混合操作测试Stream 是Java SE 8类库中新增的要害形象,它被定义于 java.util.stream (这个包里有若干流类型:Stream<T> 代表对象援用流,此外还有一系列特化流,如 IntStream,LongStream,DoubleStream等。 Java 8 引入的的Stream次要用于取代局部Collection的操作,每个流代表一个值序列,流提供一系列罕用的汇集操作,能够便捷的在它下面进行各种运算。汇合类库也提供了便捷的形式使咱们能够以操作流的形式应用汇合、数组以及其它数据结构; stream 的操作品种 ①两头操作当数据源中的数据上了流水线后,这个过程对数据进行的所有操作都称为“两头操作”;两头操作依然会返回一个流对象,因而多个两头操作能够串连起来造成一个流水线;stream 提供了多种类型的两头操作,如 filter、distinct、map、sorted 等等;②终端操作当所有的两头操作实现后,若要将数据从流水线上拿下来,则须要执行终端操作;stream 对于终端操作,能够间接提供一个两头操作的后果,或者将后果转换为特定的 collection、array、String 等;stream 的特点①只能遍历一次:数据流从一头获取数据源,在流水线上顺次对元素进行操作,当元素通过流水线,便无奈再对其进行操作,能够从新在数据源获取一个新的数据流进行操作; ②采纳外部迭代的形式:对Collection进行解决,个别会应用 Iterator 遍历器的遍历形式,这是一种内部迭代; 而对于解决Stream,只有申明解决形式,处理过程由流对象自行实现,这是一种外部迭代,对于大量数据的迭代解决中,外部迭代比内部迭代要更加高效; stream 绝对于 Collection 的长处无存储: 流并不存储值;流的元素源自数据源(可能是某个数据结构、生成函数或I/O通道等等),通过一系列计算步骤失去;函数式格调: 对流的操作会产生一个后果,但流的数据源不会被批改;感性求值: 少数流操作(包含过滤、映射、排序以及去重)都能够以惰性形式实现。这使得咱们能够用一遍遍历实现整个流水线操作,并能够用短路操作提供更高效的实现;无需上界: 不少问题都能够被表白为有限流(infinite stream):用户不停地读取流直到称心的后果呈现为止(比如说,枚举 完满数 这个操作能够被表白为在所有整数上进行过滤);汇合是无限的,但流能够表白为无线流;代码简练: 对于一些collection的迭代解决操作,应用 stream 编写能够非常简洁,如果应用传统的 collection 迭代操作,代码可能非常啰嗦,可读性也会比拟蹩脚;stream 和 iterator 迭代的效率比拟好了,下面 stream 的长处吹了那么多,stream 函数式的写法是很难受,那么 steam 的效率到底怎么呢? 先说论断: 传统 iterator (for-loop) 比 stream(JDK8) 迭代性能要高,尤其在小数据量的状况下;在多核情景下,对于大数据量的解决,parallel stream 能够有比 iterator 更高的迭代解决效率;我别离对一个随机数列 List (数量从 10 到 10000000)进行映射、过滤、排序、规约统计、字符串转化场景下,对应用 stream 和 iterator 实现的运行效率进行了统计,测试代码 基准测试代码链接 ...

June 16, 2022 · 2 min · jiezi

关于jdk:谈谈-JDK-和-SAPMachine-的关系

曾几何时,所谓 Oracle要对Java免费的新闻,在网上传得满城风雨。这个新闻被专业人士视为题目党,而国内泛滥技术论坛,比方某乎社区上,有很多大神对 Java免费 这个说法做出了十分业余的解读,笔者这里就不班门弄斧了,Bing 搜索引擎依据“Oracle Java免费”的关键字搜寻,第一条搜寻后果就很值得一读。 本文想阐述的重点,是介绍JDK,Oracle JDK, Open JDK和SAP JDK这几个名词的关系。 JDK - Java Development KitJava编程语言的软件开发工具包,是 Java 开发的外围,蕴含了Java运行环境即JVM(Java Virtual Machine)和Java零碎类库,以及大量工具。 笔者以前在 SAP 德国总部和 CRM 开发团队一位领有 20 年ABAP编程教训的德国老同事闲聊,谈到近些年来越来越多的SAP产品技术栈换成了Java,这位共事从没接触过Java,好奇地问我啥是 JDK. 我过后给他的解释是(为了节俭篇幅,笔者这里就不放英文了),“想想你在 SAPGUI 里编写的 ABAP 代码,激活后运行在C/C++实现的ABAP运行时(runtime)也就是ABAP虚拟机里。” “另外,Netweaver ABAP平台提供了很多基础设施层面的性能,比方用于HTTP通信的CL_HTTP_CLIENT和CL_HTTP_SERVER, ABAP里有很多这种类库,都存储在BASIS这个包和它的子包上面。所以ABAP Development Kit就是ABAP运行时和ABAP类库的组合,而JDK就是Java运行时和Java类库的组合,就这么简略。” 看到德国共事露出了了解后的笑容,笔者心想,有一点我没通知你,和ABAP这种Server Side的开发模式相比,用Java开发企业级利用免不了在本地搭各种开发环境,因而 Java开发人员要有在本地搭环境时可能会遇到各种各样问题的心理准备。当初笔者的敌人吴脊 2015 年退出 SAP 成都研究院时,Jerry 作为他的导师,一起在本地搭一个 Java 开发环境,最初花了一周的工夫才搭好。在那一周的工夫里,上面这句话,Jerry 说了起码不下十次: 在我电脑上是好的。 Oracle JDK创立了Java编程语言的 Sun 公司,于2009年以74亿美元的白菜价被Oracle收买之后,越来越多的Java初学者将Oracle JDK等同为JDK. 这并不奇怪,毕竟Google JDK关键字,位于搜寻后果前列的全是www.oracle.com结尾的页面: 因为Oracle和SAP的关系(SAP从业者都懂的),在Oracle旗下的Java传出“要免费”的音讯后, 一部分应用Java进行二次开发的SAP从业者们心里未免感到缓和,其实大可不必。 还记得笔者读本科的时候,一心想干掉 Java 的微软已经搞出一个叫做J++的编程语言,以及对应的Visual J++这个IDE. 不过过后笔者就读的电子科大计算机学院的编程课全用的C/C++,我四周意识的同学们也没人捣鼓这个语言。这个 J++ 尽管有着和Java雷同的语法和关键字,然而只能运行在微软的操作系统上,起初据说山寨了Java的微软被 Sun 告了,赔了20亿美元,而后就没有而后了。 ...

June 6, 2022 · 1 min · jiezi

关于jdk:赋能数据科学计算加速腾讯-Kona-JDK-蝉联-JDK18-贡献度国内第一

刚刚,Oracle 正式对外公布了 JDK18。据 Oracle 官网布告显示,腾讯 Kona 蝉联 JDK18 中国企业贡献度第一,间断四次对 OpenJDK 开源社区奉献全国第一(JDK15~18)。同时,在官网首次颁布的 OpenJDK 的综合奉献排名后果中,腾讯 Kona 的综合奉献全国第一,世界前五。 腾讯 Kona JDK 是基于 OpenJDK 开源我的项目打造的发行版之一。随着本身业务规模增长和极限能力要求,腾讯大数据专门成立了 JVM 研发团队,并通过外部开源协同策略协同全公司搭档,负责 Kona JDK 的研发和保护。在解决公司外部迫切需要的同时,踊跃奉献社区,参加了包含 JDK、Panama 和 Loom 等 OpenJDK 社区重要我的项目。在刚刚公布的 JDK18 中,Kona 向 OpenJDK 社区奉献了约 50 个 Patch。 其中,Kona JDK 针对广告模型训练、OLAP 引擎等要害业务场景的需要,研发了面向机器学习和大数据系统的高性能 Java 计算引擎,在理论业务场景中落地和利用。同时向OpenJDK社区奉献了 Vector API、主动向量化、数学库优化等代表性成绩,为解决 Java/JVM 数据迷信场景性能问题提供多种“解答思路”。 作为一组通用 Java 编程接口,Vector API 通过 Java 虚拟机生成 SIMD 向量指令来减速性能。凭借编程不便、效果显著和跨平台等特点,Vector API 第三次作为重点打造的 JEP 个性在 JDK 新版本中公布。 依据官网颁布的数据显示,Vector API 对矩阵运算等典型数据迷信场景能够达到 2~16 倍的性能减速成果。 ...

April 2, 2022 · 1 min · jiezi

关于jdk:JDKjdk18下载与安装教程

<font color=red>本教程以Windows Server 2008虚拟机演示阐明过程。</font>1、运行JDK安装包jdk-8u181-windows-x64 <img src="https://gitee.com/xuyebaodiy/img/raw/master/JDK装置阐明/image-20210731224846318.png"> 2、进入开始装置向导界面,单击下一步。如图所示。 3、抉择jdk装置目录。单击“下一步”。 4、开始装置,期待装置实现。 5、单击确定,持续装置。 6、默认抉择,单击“下一步”。 7、期待装置实现。如图所示。 8、装置实现。点击“敞开”。接下来配置环境变量。 9、配置环境变量。关上控制面板,抉择“零碎和平安”,抉择“零碎”,抉择“高级零碎设置”。如图所示。 10、关上后,抉择“环境变量”。如图所示。 11、点击零碎变量上面的“新建”按钮,进行环境变量配置。 12、变量名JAVA_HOME(代表你的JDK装置门路),值对应的是JDK的装置门路。如图所示。变量名:JAVA_HOME 变量值:C:\Program Files\Java\jdk1.8.0_181 //依据本人的理论门路配置 13、持续在零碎变量外面新建一个CLASSPATH变量,其变量值如下图所示。变量名:CLASSPATH 变量值:.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar; 14、在零碎变量外面找一个变量名是PATH的变量,须要在它的值域外面追加一段如下的代码。确定保留。%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin; 15、测试java环境变量配置是否正确。如图所示,配置实现。 流动链接:阿里巴巴开源镜像站-OPSX镜像站-阿里云开发者社区

February 23, 2022 · 1 min · jiezi

关于jdk:AdoptOpenJDK-导致的-javalangNoClassDefFoundError-问题

AdoptOpenJDK-8u312b07在应用此版本JDK时呈现以下问题: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'defaultValidator' defined in class path resource [org/springframework/boot/autoconfigure/validation/ValidationAutoConfiguration.class]: Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: Could not initialize class org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1796) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:595) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE] at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:882) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878) ~[spring-context-5.2.5.RELEASE.jar:5.2.5.RELEASE] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) ~[spring-context-5.2.5.RELEASE.jar:5.2.5.RELEASE] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141) ~[spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) ~[spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) ~[spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE] at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:140) [spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE] at org.github.helixcs.myspringboot.examples.c5.redis.JwtAppBootstrap.main(JwtAppBootstrap.java:18) [classes/:na]通过更换 OracleJDK-1.8 8u271 解决此问题。 ...

December 5, 2021 · 1 min · jiezi

关于jdk:Linux环境下安装JDK

一、筹备工作筹备JDK安装包 JDK下载地址我这里下载的是jdk-8u202-linux-x64.tar.gz这个版本卸载已有的JDk安装包(如果有) rpm -qa | grep java如果有将其卸载(remove前面跟rpm -qa | grep java命令查问进去的门路) yum -y remove二、解压装置创立目录并解压在/usr/local/下创立java文件夹 cd /usr/local/mkdir javacd java在/usr/local/java这个门路上传jdk-8u202-linux-x64.tar.gz解压 tar -zxvf jdk-8u202-linux-x64.tar.gz 解压后/usr/local/java会呈现jdk1.8.0_202,这个目录 三、配置JDK环境变量编辑/etc/profile文件,在文件最初面退出环境变量 vi /etc/profile退出环境变量 JAVA_HOME=/usr/local/java/jdk1.8.0_202CLASSPATH=$JAVA_HOME/lib/PATH=$PATH:$JAVA_HOME/binexport PATH JAVA_HOME CLASSPATH执行上面命令,让新增的环境变量失效 source /etc/profile四、验证JDK装置后果输出上面命令 java -version返回版本号则胜利 java version "1.8.0_202"Java(TM) SE Runtime Environment (build 1.8.0_202-b08)Java HotSpot(TM) 64-Bit Server VM (build 25.202-b08, mixed mode)

September 13, 2021 · 1 min · jiezi

关于jdk:从源码角度详解Java的Callable接口

摘要:本文从源码角度深刻解析Callable接口。本文分享自华为云社区《深刻解析Callable接口》,作者: 冰 河 。 本文纯干货,从源码角度深刻解析Callable接口,心愿大家踏下心来,关上你的IDE,跟着文章看源码,置信你肯定播种不小。 1.Callable接口介绍Callable接口是JDK1.5新增的泛型接口,在JDK1.8中,被申明为函数式接口,如下所示。 @FunctionalInterfacepublic interface Callable<V> { V call() throws Exception;}在JDK 1.8中只申明有一个办法的接口为函数式接口,函数式接口能够应用@FunctionalInterface注解润饰,也能够不应用@FunctionalInterface注解润饰。只有一个接口中只蕴含有一个办法,那么,这个接口就是函数式接口。 在JDK中,实现Callable接口的子类如下图所示。 默认的子类层级关系图看不清,这里,能够通过IDEA右键Callable接口,抉择“Layout”来指定Callable接口的实现类图的不同构造,如下所示。 这里,能够抉择“Organic Layout”选项,抉择后的Callable接口的子类的构造如下图所示。 在实现Callable接口的子类中,有几个比拟重要的类,如下图所示。 别离是:Executors类中的动态外部类:PrivilegedCallable、PrivilegedCallableUsingCurrentClassLoader、RunnableAdapter和Task类下的TaskCallable。 2.实现Callable接口的重要类剖析接下来,剖析的类次要有:PrivilegedCallable、PrivilegedCallableUsingCurrentClassLoader、RunnableAdapter和Task类下的TaskCallable。尽管这些类在理论工作中很少被间接用到,然而作为一名合格的开发工程师,设置是秃顶的资深专家来说,理解并把握这些类的实现有助你进一步了解Callable接口,并进步专业技能(头发再掉一批,哇哈哈哈。。。)。 PrivilegedCallablePrivilegedCallable类是Callable接口的一个非凡实现类,它表明Callable对象有某种特权来拜访零碎的某种资源,PrivilegedCallable类的源代码如下所示。 /** * A callable that runs under established access control settings */static final class PrivilegedCallable<T> implements Callable<T> { private final Callable<T> task; private final AccessControlContext acc; PrivilegedCallable(Callable<T> task) { this.task = task; this.acc = AccessController.getContext(); } public T call() throws Exception { try { return AccessController.doPrivileged( new PrivilegedExceptionAction<T>() { public T run() throws Exception { return task.call(); } }, acc); } catch (PrivilegedActionException e) { throw e.getException(); } }}从PrivilegedCallable类的源代码来看,能够将PrivilegedCallable看成是对Callable接口的封装,并且这个类也继承了Callable接口。 ...

July 28, 2021 · 3 min · jiezi

关于jdk:环境安装JDK安装

开发环境-JDK装置无论在咱们开始学习Java或者入职第一天装置环境,这个你都是必备滴!上面是下载和装置JDK的教程:1. 下载地址这里默认采纳比拟风行的jdk版本jdk1.8。https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html 关上链接,进入该页面: 往下拉,依据你的电脑系统来进行对应的版本进行抉择: 抉择完对应的版本后,要下载之前你须要首先接管协定,具体界面如下图所示: 当初下载jdk如同须要登录Oracle账户,如果没有的话还须要简略注册登录下即可下载 登录完后,就间接下载了: 下载完之后就来装置啦! 2. 装置JDK双击进行JDK版本的装置,进入装置教程,Let's GO! 抉择下一步 抉择装置门路,能够抉择本人指定,也能够默认不抉择即可。 接下来会弹出来一个Jre装置目录 到最初装置实现即可。 3. 配置零碎环境装置好jdk后,就剩下最重要的环境变量的配置了在桌面,鼠标右键 “此电脑” 抉择属性,之后会呈现一个弹窗,点击 “高级零碎设置” 在点击高级零碎设置之后,抉择 “环境变量” 开始环境变量的配置 点击零碎变量上面的新建按钮,变量名JAVA_HOME(代表你的JDK装置门路),值对应的是你的JDK的装置门路。 即: 持续在零碎变量外面新建一个CLASSPATH变量,其值为:.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar(留神后面是又有一个点的而且是一个英文状态下的小圆点),这里举荐间接复制粘贴的。配置大略如下: .;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar ![](https://img-blog.csdnimg.cn/img_convert/e83ae394124807a10e2e892347f27ec0.png)在你的零碎变量外面找一个变量名是PATH的变量,双击或者点击编辑,而后在它的值域外面追加一段如下的代码: %JAVA_HOME%\bin%JAVA_HOME%\jre\bin 配置大略如下: ![](https://img-blog.csdnimg.cn/img_convert/1a42c76ce50c0448170b90fa90121ab9.png) ![](https://img-blog.csdnimg.cn/img_convert/d5d34a5e13a5d3bacc8fbc85e7cf1483.png)而后点确定保留,进来之后再点确定,而后再点确定,至此环境变量配置结束,接下来就是测试环境变量配置有没有问题了。 在cmd模式下,输出java: 在输出java -version: 到这里你的jdk就下载配置实现啦!当然后续如果想更换其余版本的jdk的话,只须要在系统配置中的JAVA_HOME变量配置你对应想切换的jdk的版本的目录即可啦。注: 如果文章有任何谬误和倡议,请各位大佬纵情留言!也能够微信搜寻太子爷哪吒公众号进行关注一波,感激各位大佬!

June 29, 2021 · 1 min · jiezi

关于jdk:毕昇-JDK为啥是ARM-上超好用的-JDK

摘要:毕昇 JDK 是华为基于 OpenJDK 定制的开源版本,是一款高性能、可用于生产环境的 OpenJDK 发行版。本文分享自华为云社区《【云驻共创】毕昇 JDK:“传奇再现”华为如何打造 ARM 上最好用的 JDK?》,原文作者:白鹿第一帅。 前言不晓得大家是否据说过亦或是应用过毕昇 JDK,是否从事 Java 工作?是否从事 JVM 底层开发?绝大多数 Java 开发者应用的都是 Oracle 的 JDK 或者是 OpenJDK,本文咱们将介绍华为的毕昇 JDK 以及咱们所做的相干技术优化,心愿能在除上述两者之外提供给大家新的抉择。 一、什么是毕昇 JDK?1.1、毕昇 JDK 倒退历程毕昇 JDK 是华为基于 OpenJDK 定制的开源版本,是一款高性能、可用于生产环境的 OpenJDK 发行版。稳固运行在华为外部 500 多个产品上,在华为外部宽泛应用毕昇 JDK,团队积攒了丰盛的开发教训,解决了理论业务运行中遇到的多个疑难问题。如 crash 等相干问题,咱们曾经在外部解决。 1.2、毕昇 JDK 的反对架构目前仅反对 Linux/AArch64 架构。欢送宽广开发者小伙伴们下载应用。目前毕昇 JDK 反对 8 和 11 两个 LTS 版本,并且曾经全副开源。1.3、毕昇 JDK、OpenJDK 和 Oracle JDK 区别咱们通过比照和剖析毕昇 JDK、OpenJDK 和 Oracle JDK,来帮忙大家在筛选 JDK 时有更好的抉择。 如下图所示,咱们用蓝色的区域代表 OpenJDK,浅黄色和红色别离代表 Oracle JDK 和毕昇 JDK。 ...

June 9, 2021 · 3 min · jiezi

关于jdk:Ubuntu-2004-安装-JDK

如果你对 JDK 和 JRE 有什么误会或者之间有什么关系还不是十分相熟的话,请自行脑补下。 简略来说就是 JDK 是 JRE 的增强版,含有更多的工具集和 API。 在 Java 开发的时候通常都须要要求装置 JDK。 装置命令apt install default-jdk 装置命令非常简单,间接执行下面的命令就行了。 在装置的时候,咱们遇到了上面的谬误: Err:1 http://security.ubuntu.com/ub... focal-updates/main amd64 openjdk-11-jre-headless amd64 11.0.10+9-0ubuntu1~20.04 404 Not Found [IP: 91.189.88.142 80]Err:2 http://security.ubuntu.com/ub... focal-updates/main amd64 openjdk-11-jre amd64 11.0.10+9-0ubuntu1~20.04 404 Not Found [IP: 91.189.88.142 80]Err:3 http://security.ubuntu.com/ub... focal-updates/main amd64 openjdk-11-jdk-headless amd64 11.0.10+9-0ubuntu1~20.04 404 Not Found [IP: 91.189.88.142 80]Err:4 http://security.ubuntu.com/ub... focal-updates/main amd64 openjdk-11-jdk amd64 11.0.10+9-0ubuntu1~20.04 404 Not Found [IP: 91.189.88.142 80]E: Failed to fetch http://security.ubuntu.com/ub... 404 Not Found [IP: 91.189.88.142 80]E: Failed to fetch http://security.ubuntu.com/ub... 404 Not Found [IP: 91.189.88.142 80]E: Failed to fetch http://security.ubuntu.com/ub... 404 Not Found [IP: 91.189.88.142 80]E: Failed to fetch http://security.ubuntu.com/ub... 404 Not Found [IP: 91.189.88.142 80]E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing? ...

May 20, 2021 · 1 min · jiezi

关于jdk:JUC-并发类概览

JUC 并发类及并发相干类概览,继续补充... AQS外部有两个队列,一个期待队列(前后节点),一个条件队列(后继节点),其实是通过链表形式实现;期待队列是双向链表;条件队列是单向链表;条件队列如果被唤醒,将后接到期待队列上;通过外部持有的 state,加以模板模式,提供了两种资源争抢模式:排他、共享;而在争抢时,又辅以偏心、非公平竞争的思考;排他与共享别离通过子类实现的:boolean tryAcquire 和 (tryAcquireShared(x) >= 0 来判断获取资源是否胜利,同时排他限度:state 只能被一个线程批改(个别批改为 1,CAS(0,1),可重入);而共享则反对多线程同时更改 state 值(被多个线程获取);获取时要思考是否关注中断唤醒行为,对应办法名后缀:-Interruptible,关注则抛异样,不关注则革除线程的中断标记位记录,持续挂起直到获取胜利,再中断线程;总的下来,分支思考就是:资源类型(是否排他)-> 是否偏心 -> 是否关注中断(每一个都是两个方向);开释资源时,排他类型须要判断是否以后线程,而共享类型不须要判断线程,只关注资源池;排他类型会唤醒期待队列的下一个节点,而共享则会通过级联形式传递信号,从 head 开始唤醒,直到资源被新唤醒的线程抢光才进行;线程的挂起是通过 LockSupport.park(thread),反对限时挂起;state 开释导致期待队列判断,进而唤醒。限时挂起必然反对中断响应;条件队列因为初始时是通过 new ConditionObject(),能够屡次创立,所以反对多个条件队列,应用同一个对象即是同一个条件队列;被唤醒时会执行 state 的资源获取,获取不到则进入期待队列;同样反对是否中断关注;而条件队列的中断有两种状况,一种在条件队列上被中断唤醒,一种是在进入期待队列后被中断唤醒;AQS 次要是资源 state 的 CAS 并发及线程中断挂起,排队的管制AQLSstate 的类型为 long,扩大了并发数(将来扩大)。其余与 AQS 雷同。long 须要关注缓存行问题。ReentrantLock基于 AQS 实现的锁,设置 state = 1;反对偏心与非偏心(判断队列是否有期待线程);反对重入,state 递增;竞争时只有 state = 0 才获取锁胜利,否则进入期待队列;反对 condition 的 await 和 signal。CopyOnWriteArrayList与 AQS 无关,应用的 synchronized 保障同步平安;当产生增加行为时,会将原数组拷贝一份进行增加,而后更新援用;当产生指定索引增加时,会定位索引,分两步进行拷贝(索引前、索引后);适宜读多写少场景;addIfAbsent 会先判断(无同步锁),而后拷贝(有同步锁),判断时会先拷贝一份快照,在更新索引时判断快照是否最新,是则间接应用,否则从新拷贝;CopyOnWriteArraySet底层应用了 CopyOnWriteArrayList。唯一性的增加则是应用了 addIfAbsent。其余大部分办法间接调用了 CopyOnWriteArrayList 的相似办法;CountDownLatch应用了 AQS,初始化大小即为 state,每次 countDown 都是对 state - 1,而 await 则是在判断 getState() == 0 ? 1 : -1 不通过挂起在队列中,所以有多少 state 则其会被唤醒 state 次,而后从新挂起,直到 state = 0;ArrayBlockingQueue未间接应用或继承 AQS,而是通过应用 ReentrantLock 和 Condition 来实现多线程同步与挂起;外部应用数组存储元素,但不会扩大,实现了环形队列存储,队列元素减少 offer 及获取 poll 都应用 lock 进行同步;当增加胜利时,进行 notEmpty.signal() 告诉,唤醒获取失败的线程(notEmpty.await())解决;当获取胜利时,进行 notFull.signal() 告诉,唤增加失败的线程(notFulll.await())解决;offer(E) 增加返回 true/false;add(E) 外部调用 offer,返回 false 则抛异样;put 自实现,无奈增加则阻塞;poll() 获取返回 E/null,take 自实现,如果获取不到则阻塞挂起;任何增加或获取胜利,相应的都会进行 notEmpty 与 notFull 告诉,而失败则进入相同的队列挂起;ArrayBlockingQueue 的并发遍历实现是通过队列延展实现的(就是一个队列,一直的翻滚);相似于环形队列

April 12, 2021 · 1 min · jiezi

关于jdk8:JDK8至JDK-11-常用API更新

1) Optional新增: stream()ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction)or(Supplier<? extends Optional<? extends T>> supplier)版本: 9 orElseThrow()版本: 10 isEmpty()版本: 11 2) CompletableFuture新增: completeOnTimeout(T value, long timeout, TimeUnit unit)newIncompleteFuture()defaultExecutor()copy()minimalCompletionStage()completeAsync(Supplier<? extends T> supplier, Executor executor)orTimeout(long timeout, TimeUnit unit)delayedExecutor(long delay, TimeUnit unit, Executor executor)delayedExecutor(long delay, TimeUnit unit)completedStage(U value)failedFuture(Throwable ex)failedStage(Throwable ex)版本: 9 3) Stream新增: takeWhile(Predicate<? super T> predicate)dropWhile(Predicate<? super T> predicate)ofNullable(T t)iterate(T seed, Predicate<? super T> hasNext, UnaryOperator<T> next)版本: 9 4) Map新增: of() 系列办法entry(K k, V v)版本: 9 copyOf(Map<? extends K,? extends V> map)版本: 10 ...

March 18, 2021 · 2 min · jiezi

关于jdk:ConcurrentHashMap-的-Traverser-阅读

ConcurrentHashMap 源码目前在网络上已有泛滥解析。本文章次要关注其基于 Traverser 的遍历实现,试图认真解析该实现,如有错漏,请斧正。 ConcurrentHashMap 的 Traverser 次要是用于外部数组的遍历性能反对,如何实现在外部数组扩容阶段期间,其余线程也可能正确地遍历输入,并保障良好的性能(不应用各种锁),Traverser 提供了一个优良的设计实现。 1. 相干概念 2. 解析 1.相干概念 1.1 ConcurrentHashMap 反对办法 forEach(Consumer<? super K> action)、keys、elements、contains 等办法,它们的外部实现都基于 Traverser; 1.2 ConcurrentHashMap 的遍历可能保障在外部数组扩容期间,也具备优良的性能和并发安全性。 1.3 Traverser 的次要办法:advance,其示意为:推动,与扩容期间时的 boolean 变量 advance 具备类似的意义,都是推动索引(index)的增长,以便继续向前推动元素定位。 1.4 了解在 类 Traverser  中的变量的命名,有利于对实现的了解,如:baseXxx 的变量是针对 ConcurrentHashMap 中的旧表,没有 base- 前缀的则同时针对旧表与新表(以后遍历上下文)。 2.解析 2.1 ConcurrentHashMap 对立了遍历的根底实现,即:Traverser 负责元素推动,并将元素返回;而 BaseIterator 则负责对元素进行判断,并提供迭代实现:hasNext、next;XxxIterator 则是基于 BaseIterator 提供不同的实现:针对 keys 的迭代、针对 value 的迭代、针对 entry 的迭代。   2.2 Traverser 类放弃了迭代的索引:index,和对所在 ConcurrentHashMap 的外部数组—— 可能是旧表,也可能是新表的援用 ...

December 15, 2020 · 5 min · jiezi

关于jdk:Oracle-要慌了华为终于开源了自家的-Huawei-JDK毕昇-JDK

没错,自阿里、腾讯之后,华为也终于开源了自家的 JDK——毕昇 JDK! 收费!收费!收费!!! Oracle 要慌了? 毕昇 JDK 毕昇 JDK 是华为外部 定制版 Huawei JDK 的开源版本,是一个高性能、可用于生产环境的 OpenJDK发行版。 Huawei JDK 运行在华为外部 500 多个产品上,积攒了大量应用场景和 Java 开发者反馈的问题和诉求,解决了业务理论运行中遇到的多个问题,并在 ARM 架构上进行了性能优化,毕昇 JDK 运行在大数据等场景下能够取得更好的性能。 毕昇 JDK 8 与 Java SE 规范兼容,同时是OpenJDK 的上游,对一些华为外部利用场景上遇到的性能和稳定性问题进行了修复,并在 ARM 架构上进行了性能优化和稳定性加强,在 ARM 架构上更稳固,在大数据等场景下能够取得更好的性能。 毕昇 JDK 当初和将来也会继续稳固为 OpenJDK 社区做出奉献。 平台反对 1)毕昇 JDK 目前只反对基于 OpenJDK 8 和 11 两个 LTS 版本。 2)毕昇 JDK 以后反对 Linux/AArch64 平台。 装置指南 能够应用 tar 压缩包格局或者 yum 源形式来装置 JDK(Java Development Kit)或者 JRE(Java Runtime Environment)。 ...

December 15, 2020 · 1 min · jiezi

关于jdk:openJDK系列1macos编译openJDK-8

背景因为之前始终在钻研jdk源码,然而基于本人比拟懒的缘故,始终没有手动编译过jdk源码,也就只是看看书本上的货色,似懂非懂的看懂了也就草草了事了,这次终于下定决心编译一把openJDK8的源码 根底环境macos High Sierra 10.13.1 openJDK 8 编译间接找到 http://hg.openjdk.java.net/ ,执行以下命令 # 装置mercurialbrew install mercurial# clone openJDK源码hg clone http://hg.openjdk.java.net/jdk8/jdk8 openjdk8当然在git JDK也有对应的JDK源码,git clone之后checkout到对应的tag上进行编译也是能够的 git clone https://github.com/openjdk/jdkgit checkout -b openjdk8 jdk8-b80留神如果是用hg clone的形式咱们还得执行sh ./get_source.sh命令来获取额定的文件,对于Mercurial和Git的区别,网上一大堆,网友能够自行查找,操作形式能够参考hg git 操作咱们这里抉择hg clone的形式,执行 cd openjdk8 && sh ./get_source.sh装置依赖 brew install freetypeRunning Configure bash ./configure --with-debug-level=slowdebug --with-boot-jdk=/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home --with-freetype-include=/usr/local/Cellar/freetype/2.10.4/include/freetype2 --with-freetype-lib=/usr/local/Cellar/freetype/2.10.4/lib --with-target-bits=64 --with-jvm-variants=server --with-jdk-variant=normal --with-milestone=internal --with-num-cores=2 --with-jobs=4 CC=clang CXX=clang++其中, 名词阐明--with-boot-jdk用于bootstrap build,指向本地已有的jdk--with-freetype-includefreetype include文件目录--with-freetype-libfreetype lib目录--with-target-bits编译成64还是32位jdk--with-jvm-variantsjvm 的模式如server,client,kernel等,多个用逗号离开--with-jdk-variantjdk的模式,会在build目录下生成的文件下有体现--with-milestonebuild的里程碑,也就是阶段,会在build目录下生成的文件下有体现--with-num-cores用于此次build的核数--with-jobsbuild的并发工作数CCC 编译器命令,如:clang,gccCXXC++编译器命令,如:clang++,g++对于clang和gcc的区别,参考clang和gcc的区别make编译执行如下命令: make COMPILER_WARNINGS_FATAL=false LFLAGS='-Xlinker -lstdc++' CC=clang USE_CLANG=true LP64=1 其中, ...

November 24, 2020 · 2 min · jiezi

关于jdk:第三阶段-Day01

京淘我的项目环境搭建============ 1.1 JDK配置1.1.1 JDK环境阐明 1.1.2 JDK环境变量配置 1.2 Maven配置1.2.1 私服镜像配置 `<mirror> <id>aliyun</id> <name>aliyun for maven</name> <mirrorOf>*</mirrorOf> <url>https://maven.aliyun.com/repository/public</url> </mirror>` 1.2.2 本地仓库地位 1.3 STS配置1.3.1 配置字符集编码格局 1.3.2 查看JDK配置 1.3.3 引入maven1).配置maven环境2).编辑maven配置文件 1.3.4 敞开校验 1.4 构建SpringBoot入门我的项目1.4.1 创立我的项目 1.4.2 创立我的项目(二) 2 京淘我的项目概述 3.SpringBoot框架高级阐明3.1 parent标签的作用`<!--1.jar包品种繁多 A.jar 1.0版本 B.jar 2.0版本 C.jar 3.0版本 A.jar 2.0版本 B.jar 2.0版本 C.jar 3.0版本 晚期的jar包版本 可能呈现jar包抵触的问题. 所有采纳parent标签的形式 对立定义了版本号 由官网本人进行测试, 将容许稳固的版本对立的治理. --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.2.RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent>` 3.2 对于maven 插件的阐明`<!-- maven我的项目指定的插件配置 该插件次要负责 maven我的项目相干操作 打包/test/clean/update 等相干maven操作 注意事项:但但凡maven我的项目则必须增加 插件.否则未来我的项目部署必然出错 --> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>` 3.3 对于Maven 属性的配置`<!--以后maven配置信息 --> <properties> <java.version>1.8</java.version> <!--定义maven插件版本 --> <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version> <skipTests>true</skipTests> </properties>` 3.4 对于Maven依赖阐明3.4.1 依赖与本地仓库的关系`<!--maven的依赖 利用坐标的模式治理jar包 本地仓库之间有什么关系呀? --> <dependency> <!--组ID, 公司域名倒写. --> <groupId>org.springframework.boot</groupId> <!--具体项目名称 --> <artifactId>spring-boot-starter-web</artifactId> <!--版本号 被parent标签提前定义 --> <!-- <version>2</version> --> </dependency>` 2).本地仓库内容3).规定阐明如果当前下载jar包时,遇到maven依赖异样.则首先查问本地仓库中是否有该jar包的残缺版本.如果发现jar包文件下载不齐全,则须要删除之后从新下载. ...

October 22, 2020 · 14 min · jiezi

关于jdk:JVMJREJDK之间的区别和联系

JDK蕴含了JRE,JRE蕴含了JVMJDK:java开发工具包,针对java开发人员,能够编译运行java程序JRE:java运行时环境,针对应用java程序的客户,能够运行字节码(.class),然而不能编译Java源码JVM:用来解释执行字节码文件(.class),但不能正确的执行什么是JVMJVM是JRE的一部分,是虚构进去的一台计算机.通过实体计算机仿真各种计算性能来实现,JVM有本人欠缺的硬件架构,如处理器,堆栈,寄存器等,还有相应的指令集.JVM是Java跨平台的外围,Java程序通过JVM的跨平台,从而使Java程序跨平台.Java程序首选会被编译成字节码文件(.class),JVM的外围工作就是解释字节码文件(.class)并映射到实在CPU指令集或者零碎调用.JVM不关系下层Java程序,只关系字节码(.class).什么是JREJRE是Java运行环境,所有Java程序必须依赖JRE能力运行.只有JVM是不能运行字节码文件的(.class),因为解释的字节码的时候须要lib库. JRE外面有两个文件夹bin/,lib/。bin/就是JVM,lib就是JVM所须要库。JVM+lib=JRE什么是JDKJDK是Java的外围,蕴含运行Java运行环境(JRE)和一些Java工具及Java根底类库 。JDK提供的工具 appletviewer.exe* java-rmi.exe* jrunscript.exe* policytool.exe*extcheck.exe* javaw.exe* jsadebugd.exe* rmic.exe*idlj.exe* javaws.exe* jstack.exe* rmid.exe*jabswitch.exe* jcmd.exe* jstat.exe* rmiregistry.exe*jar.exe* jconsole.exe* jstatd.exe* schemagen.exe*jarsigner.exe* jdb.exe* jvisualvm.exe* serialver.exe*java.exe* jdeps.exe* keytool.exe* servertool.exe*javac.exe* jhat.exe* kinit.exe* tnameserv.exe*javadoc.exe* jinfo.exe* klist.exe* unpack200.exe*javafxpackager.exe* jjs.exe* ktab.exe* vcruntime140.dll*javah.exe* jli.dll* native2ascii.exe* wsgen.exe*javap.exe* jmap.exe* orbd.exe* wsimport.exe*javapackager.exe* jps.exe* pack200.exe* xjc.exe*Java Api是Java的利用程序接口,外面有很多写好的Java Class,蕴含一些重要的语法结构以及根本图形,网络和文件IO,咱们能够间接调用。 总结有JVM和lib库(JRE)就能够执行字节码(.class)文件(Java程序)有JRE能够运行(Java程序)然而还不能开发Java程序,须要JDK(JRE+开发工具)才能够windows 装置jdk 会发现有两个目录,其实只须要jdk1.8.0_91就能够,里面包好了jre,jre1.8.0_91是JDK独自提供一个一个运行环境 两个目录jre的区别相同点:这两个JRE都能够作为Java程序的运行环境不同点:JDK只能应用本人目录自带的JRE,不能应用里面独自装置的JRE开发到运行装置JDK环境,调用本地的Java api实现业务代码,通过JDK的编译器(javac)编译成字节码(.class),而后在JRE上运行这些JAVA字节码,JVM解释这些字节码,映射到CPU指令集或者零碎调用。

October 13, 2020 · 1 min · jiezi

关于jdk:JDK15真的来了一起来看看它的新特性

简介一年两次的JDK最新版本JDK15在2020年9月15日正式公布了,这次的JDK15给咱们带了暗藏类,EdDSA,模式匹配,Records,关闭类和Text Block等诸多新个性。 一起来看看吧。 JDK15的新个性JEP 385 Deprecate RMI Activation for RemovalRMI Activation被标记为Deprecate,将会在将来的版本中删除。 RMI大家应该都分明,RMI就是Remote Method Invocation,翻译成中文就是近程办法调用,是在JDK1.2中引入的。 RMI为java提供了开发分布式系统的弱小能力。而J2EE的标准EJB就是应用RMI来实现的bean的近程调用的。 在RMI零碎中,近程零碎中存在很多分布式对象,如果这些分布式对象始终处于活动状态的话,将会占用很多贵重的系统资源。 于是RMI引入了一种lazy Activation的形式,这种形式就叫做提早激活。 这里有两个概念,流动对象和被动对象。 流动对象是在某些零碎上的JVM中实例化并对外裸露的近程对象。被动对象是尚未在JVM中实例化(或裸露)但能够进入被动状态的对象。 将被动对象转换为被动对象的过程称为激活。激活要求对象与JVM关联,这可能会将该对象的类加载到JVM中,并且将该对象复原为之前的状态。 在RMI零碎中,咱们应用提早激活。提早激活将激活对象推延到客户第一次应用(即第一次办法调用)之前。 既然RMI Activation这么好用,为什么要废除呢? 因为对于古代应用程序来说,分布式系统大部分都是基于Web的,web服务器曾经解决了穿梭防火墙,过滤申请,身份验证和安全性的问题,并且也提供了很多提早加载的技术。 所以在古代应用程序中,RMI Activation曾经很少被应用到了。并且在各种开源的代码库中,也基本上找不到RMI Activation的应用代码了。 为了缩小RMI Activation的保护老本,在JDK8中,RMI Activation被置为可选的。当初在JDK15中,终于能够废除了。 JEP 371 Hidden ClassesHidden Classes是什么呢? Hidden Classes就是不能间接被其余class的二净值代码应用的class。Hidden Classes次要被一些框架用来生成运行时类,然而这些类不是被用来间接应用的,而是通过反射机制来调用。 通常来说基于JVM的很多语言都有动静生成类的机制,这样能够进步语言的灵活性和效率。 比方在JDK8中引入的lambda表达式,JVM并不会在编译的时候将lambda表达式转换成为专门的类,而是在运行时将相应的字节码动静生成相应的类对象。 另外应用动静代理也能够为某些类生成新的动静类。 那么咱们心愿这些动静生成的类须要具备什么个性呢? 不可发现性。因为咱们是为某些动态的类动静生成的动静类,所以咱们心愿把这个动静生成的类看做是动态类的一部分。所以咱们不心愿除了该动态类之外的其余机制发现。访问控制。咱们心愿在访问控制动态类的同时,也能管制到动静生成的类。生命周期。动静生成类的生命周期个别都比拟短,咱们并不需要将其保留和动态类的生命周期统一。然而现有的类的定义API ClassLoader::defineClass和Lookup::defineClass是不论类的字节码是如何生成的,他们都是平等看待。 所以咱们须要一些API来定义无奈发现的且具备无限生命周期的暗藏类。这将进步所有基于JVM的语言实现的效率。 比方: java.lang.reflect.Proxy能够定义暗藏类作为实现代理接口的代理类。 java.lang.invoke.StringConcatFactory能够生成暗藏类来保留常量连贯办法; java.lang.invoke.LambdaMetaFactory能够生成暗藏的nestmate类,以包容拜访关闭变量的lambda主体; JavaScript引擎能够为从JavaScript程序转换的字节码生成暗藏的类,因为当引擎不再应用它们时,这些类将被卸载。 一般类是通过调用ClassLoader::defineClass创立的,而暗藏类是通过调用Lookup::defineHiddenClass创立的。 这使JVM从提供的字节中派生一个暗藏类,链接该暗藏类,并返回提供对暗藏类的反射拜访的查找对象。 调用程序能够通过返回的查找对象来获取暗藏类的Class对象。 JEP 339 Edwards-Curve Digital Signature Algorithm (EdDSA)实现了EdDSA椭圆曲线签名算法。 这里就不多讲椭圆曲线签名算法了,如果又想理解的敌人能够给我留言。 JEP 375 Pattern Matching for instanceof (Second Preview)Pattern Matching 就是说能够在做pattern mathching的时候,间接对该对象进行类型的转换。 ...

September 16, 2020 · 3 min · jiezi

关于jdk:金九银十想面BAT那这些JDK-动态代理的面试点你一定要知道

一、什么是代理代理是一种罕用的设计模式,其目标就是为其余对象提供一个代理以管制对某个对象的拜访。代理类负责为委托类预处理音讯,过滤音讯并转发音讯,以及进行音讯被委托类执行后的后续解决。 代理模式UML图: 构造示意图: 为了放弃行为的一致性,代理类和委托类通常会实现雷同的接口,所以在访问者看来两者没有丝毫的区别。通过代理类这两头一层,能无效管制对委托类对象的间接拜访,也能够很好地暗藏和爱护委托类对象,同时也为施行不同控制策略预留了空间,从而在设计上取得了更大的灵活性。Java 动静代理机制以奇妙的形式近乎完满地实际了代理模式的设计理念。 二、Java动静代理Java动静代理类位于java.lang.reflect包下,个别次要波及到以下两个类:(1)Interface InvocationHandler:该接口中仅定义了一个办法 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;在理论应用时,第一个参数proxy个别是指代理类,method是被代理的办法,如上例中的request( ),args为该办法的参数数组。这个形象办法在代理类中动静实现。(2)Proxy:该类即为动静代理类,其中次要蕴含以下内容(API): //所在包package java.lang.reflect;//Proxy类的定义public class Proxy implements java.io.Serializable {}Proxy提供了用于创建对象的静态方法,这些对象充当接口实例但容许自定义办法调用。 要为接口Foo创立代理实例: InvocationHandler handler = new MyInvocationHandler(...); Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), new Class<?>[] { Foo.class }, handler); 1、构造函数,用于给外部的h赋值 protected Proxy(InvocationHandler h)2、取得一个代理类,其中loader是类装载器,interfaces是实在类所领有的全副接口的数组。 static Class getProxyClass (ClassLoaderloader, Class[] interfaces)3、返回代理类的一个实例,返回后的代理类能够当作被代理类应用(可应用被代理类的在Subject接口中申明过的办法): static Object newProxyInstance(ClassLoaderloader, Class[] interfaces, InvocationHandler h)所谓DynamicProxy是这样一种class:它是在运行时生成的class,在生成它时你必须提供一组interface给它,而后该class就声称它实现了这些 interface。你当然能够把该class的实例当作这些interface中的任何一个来用。当然,这个DynamicProxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管理论的工作。在应用动静代理类时,咱们必须实现InvocationHandler接口通过这种形式,被代理的对象(RealSubject)能够在运行时动静扭转,须要管制的接口(Subject接口)能够在运行时扭转,管制的形式(DynamicSubject类)也能够动静扭转,从而实现了非常灵活的动静代理关系。 动静代理的步骤: 创立一个实现接口InvocationHandler的类,它必须实现invoke办法创立被代理的类以及接口通过Proxy的静态方法newProxyInstance(ClassLoaderloader, Class[] interfaces, InvocationHandler h)创立一个代理通过代理调用办法三、具体应用1、须要动静代理的接口: ...

September 14, 2020 · 9 min · jiezi

关于jdk:mac实现不同版本的jdk切换

之前应用jdk11进行java开发(纯正因为喜爱新版????)然而应用jdk11在布署hadoop伪散布时各种报错, 所以还是下载jdk8回来. 接下来就是mac端切换两个版本的jdk(依照网上找的形式如同有bug-文章最初再说.尽管不晓得怎么解决,然而至多我能够胜利部署hadoop, 所以这里就先疏忽) 首先下载jdk8JDK8官网下载而后一路next装置就好接下来就是重点啦 首先要晓得本人的jdk是装置在哪里的.比方我的门路是 在上面的文件中输出的时候, 只有到Home这个文件夹的层级就好 接下来在终端中输出open ~/.bash_profile关上文件 关上后, 在内容最底部输出上面的内容 export JAVA_8_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_261.jdk/Contents/Homeexport JAVA_11_HOME=/Library/Java/JavaVirtualMachines/adoptopenjdk-11.jdk/Contents/Homealias jdk8='export JAVA_HOME=$JAVA_8_HOME'alias jdk11='export JAVA_HOME=$JAVA_11_HOME'下面两个门路就依据本人理论门路批改就好. 写好后保留,敞开, 在终端中输出source ~/.bash_profile"重启"这个文件. 至此, 当初两个版本的JDK就能够切换了, 看下成果 这样子能够看到切换胜利了. 下面说的bug的意思是, 我切换在jdk8后敞开终端, 再次关上终端, 再次输出java -version, 显示的还是jdk11. 所以就是主动切换回了jdk11. 这里就不晓得是为什么了敞开终端再关上,就主动是jdk11

September 9, 2020 · 1 min · jiezi

关于jdk:JDK源码分析Integer

一. 根本形容java.lang.Integer是最罕用的Java类型之一,然而恐怕很少有人会去留神这个撑持起整个Java世界的小小基石。 Integer类的申明是 public final class Integer extends Number implments Comparable<Integer>,咱们能够发现Integer类是不能被继承的。 Integer的外围字段是private final int value,这个字段代表着Integer对象所示意的整数值,final修饰符意味着Integer是immutable即不可变的。 还有一个乏味的中央在Integer的哈希办法 @Overridepublic int hashCode() { return Integer.hashCode(value);}public static int hashCode(int value) { return value;}Integer的哈希办法间接返回了整数示意 二. reverse办法reverse办法的实现很有意思 public static int reverse(int i) { i = (i & 0x55555555) << 1 | (i >>> 1) & 0x55555555; i = (i & 0x33333333) << 2 | (i >>> 2) & 0x33333333; i = (i & 0x0f0f0f0f) << 4 | (i >>> 4) & 0x0f0f0f0f; i = (i << 24) | ((i & 0xff00) << 8) | ((i >>> 8) & 0xff00) | (i >>> 24); return i; }咱们一步步剖析,首先是第一行i = (i & 0x55555555) << 1 | (i >>> 1) & 0x55555555留神了啊,很多人对16进制不敏感,16进制的0x5开展成二进制就是0101,0x55555555就是01010101010101010101010101010101,那么代码前半部分(i & 0x55555555) << 1的性能是只保留整数i的偶数位(从0开始计数)并左移一位,代码后半局部(i >>> 1) & 0x55555555的性能是只保留整数i的奇数位第一行代码合起来所实现的性能就是将i的二进制每2位划为一组,并将组内的位替换地位。相似的,0x3开展成二进制就是0011,第二行代码的性能就是将i的二进制每4位划为一组,并将组内的前两位和后两位替换地位。 ...

August 15, 2020 · 2 min · jiezi

关于jdk:JDK源码环境搭建

本教程是用idea搭建,jdk源码就在jdk装置门路下的src.zip中,解压即可用。第一步:新建我的项目关上IDEA,按如下步骤新建一个简略Java我的项目 create new project 新建一个简略Java我的项目 点击finish后,我的项目就创立好了 第二步:增加源码将之前解压的src.zip复制到工程目录下 第三步:替换JDK关联为了可能备注以及防止批改到其余我的项目所应用的内容,增加一个名为“JavaJDK1.8Funyard”的SDK 并将Sourcepath批改为以后我的项目src下的源码内容 移除Sourcepath中关联的src.zip 将我的项目中的JDK源码关联到Sourcepath 批改我的项目应用的JDK为下面新建的 第四步:解决系统资源有余(OutOfMemoryError)顺次点击File–>Settings–>Build,Execution,Deployment–>Compiler 堆大小可由原来的700改为1700 第五步:解决Debugger断点进入不了下一层[外链图片转存失败,源站可能有防盗链机制,倡议将图片保留下来间接上传(img-pj72YmKR-1586181006241)(C:UsersliuweiAppDataRoamingTyporatypora-user-images1586180987620.png)] 第六步:解决com.sun.tools.javac.api不存在将jdk装置目录下(不是本人新建的这个源码浏览工程)lib包增加到我的项目中 仍然是Projuect Structure 点击ok,实现 第七步:解决找不到sun.awt.UNIXToolkit和sun.font.FontConfigManager在我的项目中新建sun.awt包和sun.font包,别离新建UNIXToolkit.java和FontConfigManager.java 到OpenJDK寻找sun.awt.UNIXToolkit和sun.font.FontConfigManager的源码,别离复制到下面新建的两个类里 抉择对应版本jdk 寻找UNIXToolkit类 进入到 /src/solaris/classes/sun/awt/目录,找到UNIXToolkit FontConfigManager也是一样,门路:src/solaris/classes/sun/font/FontConfigManager.java 复制进去之后能够看到还是有谬误的中央,这时候就要进行清理idea缓存而后重启: 点击左上角File->Invalidate Caches/Restart… 重启之后就能够顺利运行啦(下面新建的类中可能还会报error,然而对应用没有影响)

August 7, 2020 · 1 min · jiezi

关于jdk:JDK安装及环境变量配置流程

jdk装置与配置环境变量1、下载jdk JDK1.8官网链接地址 https://www.oracle.com/java/t... 点击下载,下载完后装置,间接点击下一步。 可更改你要装置的地位(要记住这个地位,前面环境变量配置用到了) 2、环境变量配置 装置完JDK后配置环境变量  计算机→属性→高级零碎设置→高级→环境变量 零碎变量→新建 JAVA_HOME 变量 。 变量值填写jdk的装置目录(自己是D:Program Filesjdk1.8) 3、零碎变量path配置 零碎变量→寻找 Path 变量→编辑 在变量值最初输出 %JAVA_HOME%\bin;%JAVA_HOME%\jre\bin; (留神原来Path的变量值开端有没有;号,如果没有,先输出;号再输出下面的代码) 4、零碎变量CLASSPATH配置 零碎变量→新建 CLASSPATH 变量 变量值填写   .;%JAVA_HOME%libdt.jar;%JAVA_HOME%libtools.jar(留神最后面有一点) 零碎变量配置结束 5、测验是否配置胜利 装置实现之后,咱们运行命令,测验是否配置胜利 运行cmd 输出 java -version 小编不易,如有播种,微信赏小编喝杯娃哈哈 独身狗的 葵花宝典,撩妹必备 敬请关注!

August 3, 2020 · 1 min · jiezi

一张PDF了解JDK9-GC调优秘籍附PDF下载

简介今天我们讲讲JDK9中的JVM GC调优参数,JDK9中JVM的参数总共有2142个,其中正式的参数有659个。好像比JDK8中的参数要少一点。 为了方便大家的参考,特意将JDK9中的GC参数总结成了一张PDF,这个PDF比之前总结的JDK8的PDF在排版,颜色和内容准确性上面又有了非常大的提升,欢迎大家下载。 Oracle中的文档今天这篇文章的内容都是从Oracle JDK9的官方文档中提炼出来的。对于里面的内容的真实性,我不能保证是100%正确的。 有人要问了,官网文档也会有错误? 这个问题要从两个方面说起,第一方面,任何人都会犯错误,虽然官网文档经过了编辑,校验核对然后才发布,但是总会有一些遗漏的地方。 第二,Oracle的文档是有专门的写文档的部门来专门编写的,写文档就是他们的工作,所以,这些文档并不是开发JDK的开发人员编写的,而是和开发JDK不相关的文档编写员编写的。 至于文档写完之后有没有JDK开发人员过目,大家可以自行脑补...... 所以古人说得好,尽信书不如无书。JDK9中JVM参数的变化一代新人换旧人,长江后浪推前浪。由来只有新人笑 有谁听到旧人哭。 JDK9出现了,那么JDK8中的一些参数自然需要退伍了。 我们回想一下JDK9中有些什么变化呢?我总结一下有三个。 最大的变化就是引入了JPMS(Java Platform Module System)也就是Project Jigsaw。模块化的本质就是将一个大型的项目拆分成为一个一个的模块,每个模块都是独立的单元,并且不同的模块之间可以互相引用和调用。 在module中会有元数据来描述该模块的信息和该模块与其他模块之间的关系。这些模块组合起来,构成了最后的运行程序。 然后就是引入的Xlog日志服务,通过Xlog日志服务我们可以监控JVM中的事件,比如:GC,class loading,JPMS,heap,thread等等。最后就是将String中的底层存储从char数组换成了byte数组。这三个变化中和JVM最相关的就是第二个Xlog日志服务。 废弃的JVM选项-Xusealtsigs / -XX:+UseAltSigs 这两个选项在JDK9中被废弃了,如果你不知道也没关系,因为这两个选项是在Oracle Solaris中专有的。现在用Solaris服务器的人应该比较少了..... 不推荐(Deprecated)的JVM选项下面这些选项是JVM已经不再推荐使用了,如果你使用的话也没问题,但是会有报警。 Deprecated表示这些选项会在未来被删除,我们应该尽量避免使用这些选项。 选项有很多,我们挑一些比较常见和重要的来给大家讲解一下。 -d32 / -d64 为什么这两个参数会被不推荐呢?因为现在的服务器性能已经非常非常的好了。 如果你的JDK是64位的,那么默认就启用了-server和-d64模式,32位的JDK现在应该很少见到了。 Oracle官方文档说只有Java HotSpot Server VM才有64位的模式。不知道是真是假,因为其他的VM我也没有用过,没有发言权。-Xloggc:garbage-collection.log 因为JDK9中引入Xlog框架,所以之前的日志输出的参数都被替换成了新的Xlog格式: 比如上面的命令被替换成为 -Xlog:gc:garbage-collection.log 所以那些以Print开头的GC日志输出参数都是不推荐的。我们需要使用Xlog来替代。 同样的以Trace开头的运行时日志输出参数也是不推荐的,也可以使用Xlog来替代。 -XX:+UseConcMarkSweepGC / -XX:CMS* CMS在JDK9中是不被推荐的,所以CMS开头的参数都不要用了。 -XX:+UseParNewGC 因为ParNewGC是和CMS一起使用的,所以CMS不推荐之后,ParNewGC也是不推荐使用的。 -XX:MaxPermSize=size / -XX:PermSize=size JDK8中,Prem区已经被移到了Metaspace,所以上面的参数可以被下面的替代: -XX:MaxMetaspaceSize=size / -XX:MetaspaceSize=size 被删除的JVM参数-Xincgc 增量GC在JDK9中被删除了。 -Xmaxjitcodesize=size JIT中最大的code cache大小被替换成 -XX:ReservedCodeCacheSize。 还有其他的一些CMS的参数。 JDK9的新特性Application Class Data SharingAppCDS的全称是Application Class-Data Sharing。主要是用来在不同的JVM中共享Class-Data信息,从而提升应用程序的启动速度。 ...

June 30, 2020 · 1 min · jiezi

Semaphore-原理简介和使用

Semaphore共享锁简介`在多线程环境下用于协调各个线程, 以保证它们能够正确、合理的使用公共资源 信号量维护了一个许可集,我们在初始化Semaphore时需要为这个许可集传入一个数量值, 该数量值代表同一时间能访问共享资源的线程数量。 线程可以通过acquire()方法获取到一个许可,然后对共享资源进行操作, 如果许可集已分配完了,那么线程将进入等待状态, 直到其他线程释放许可才有机会再获取许可,线程释放一个许可通过release()方法完成 ` DEMO了解其用法 `上述示例说明: 在创建Semaphore时初始化5个许可,这也就意味着同一个时间点允许5个线程进行共享资源访问, 使用acquire()方法为每个线程获取许可,并进行休眠1秒,如果5个许可已被分配完, 新到来的线程将进入等待状态。如果线程顺利完成操作将通过release()方法释放许可, 我们执行代码,可以发现每隔1秒几乎同一时间出现5条线程访问 ` Semaphore实现互斥锁简介`在初始化信号量时传入1,使得它在使用时最多只有一个可用的许可,从而可用作一个相互排斥的锁。 这通常也称为二进制信号量,因为它只能有两种状态:一个可用的许可或零个可用的许可。 按此方式使用时,二进制信号量具有某种属性(与很多 Lock 实现不同),即可以由线程释放“锁”,而不是由所有者(因为信号量没有所有权的概念) ` DEMO了解其用法 `创建一个数量为1的互斥信号量Semaphore, 然后并发执行10个线程,在线程中利用Semaphore控制线程的并发执行, 因为信号量数值只有1,因此每次只能一条线程执行,其他线程进入等待状态 ` Semaphore提供的方法Semaphore(int permits) 创建具有给定的许可数和非公平的公平设置的SemaphoreSemaphore(int permits, boolean fair) 创建具有给定的许可数和给定的公平设置的Semaphore,true即为公平锁void acquireUninterruptibly() 从此信号量中获取许可,不可中断int availablePermits() 返回此信号量中当前可用的许可数int drainPermits() 获取并返回立即可用的所有许可protected Collection<Thread> getQueuedThreads() 返回一个 collection,包含可能等待获取的线程int getQueueLength() 返回正在等待获取的线程的估计数目boolean hasQueuedThreads() 查询是否有线程正在等待获取boolean isFair() 如果此信号量的公平设置为 true,则返回 trueboolean tryAcquire() 仅在调用时此信号量存在一个可用许可,才从信号量获取许可boolean tryAcquire(long timeout, TimeUnit unit) 如果在给定的等待时间内,此信号量有可用的许可并且当前线程未被中断,则从此信号量获取一个许可内部原理分析类图 `AQS是基础组件,只负责核心并发操作,如加入或维护同步队列,控制同步状态,等, 而具体的加锁和解锁操作交由子类完成, 因此子类Semaphore共享锁的获取与释放需要自己实现, 这两个方法分别是获取锁的tryAcquireShared(int arg)方法和释放锁的tryReleaseShared(int arg)方法,这点从Semaphore的内部结构完全可以看出来 ` `Semaphore的内部类公平锁(FairSync)和非公平锁(NoFairSync)各自实现不同的获取锁方法即tryAcquireShared(int arg), 毕竟公平锁和非公平锁的获取稍后不同, 而释放锁tryReleaseShared(int arg)的操作交由Sync实现,因为释放操作都是相同的,因此放在父类Sync中实现当然是最好的 ` 源码分析 ...

June 28, 2020 · 1 min · jiezi

阿里放大招要干掉oracle推出国产开源的JDK

简介Alibaba Dragonwell 是一款免费的, 生产就绪型Open JDK 发行版,提供长期支持,包括性能增强和安全修复。阿里巴巴拥有最丰富的Java应用场景,覆盖电商,金融,物流等众多领域,世界上最大的Java用户之一。Alibaba Dragonwell作为Java应用的基石,支撑了阿里经济体内所有的Java业务。Alibaba Dragonwell完全兼容 Java SE 标准,您可以在任何常用操作系统(包括 Linux、Windows 和 macOS)上开发 Java 应用程序, 运行时生产环境选择Alibaba Dragonwell。 特性安全与稳定紧密与 OpenJDK 社区保持合作,保持对社区工作的跟踪,及时同步上游更新;同时,Dragonwell 选择性的移植高版本 Java 的重要功能,这些移植功能已经在阿里内部被大规模部署,用户都可以免费使用,而不用等下一个 LTS 版本 标准兼容OpenJDK 的下游, 完全遵循 Java SE 标准,通过 JCK 兼容性测试 性能卓越Dragonwell 作为阿里巴巴 Java 应用的基石,支撑了阿里经济体内所有的 Java 业务,积累了大量业务场景下的实践和创新 精心打造的功能Alibaba Dragonwell 会针对 Long Term Support(LTS) 提供 Java 8 和 Java 11两个版本 长期支持阿里巴巴提供季度更新,Java8 更新至少到 2023 年 6月,Java11 更新至少到 2024 年 6月 免费Dragonwell随阿里云 VM 镜像发布,免费提供给阿里云客户使用;开发者也可以直接下载免费使用 场景介绍Java 应用基础运行时Java 应用基础运行时,可用作许多 Java SE 发行版的简易替代 ...

June 24, 2020 · 1 min · jiezi

阿里巴巴开源-Dragonwell-JDK-最新版本-811GA-发布

导读:新版本主要有三大变化:同步了 OpenJDK 上游社区 jdk8u222-ga 的最新更新;带来了正式的 feature:G1ElasticHeap;发布了用户期待的 Windows 实验版本 Experimental Windows version。距离 Dragonwell JDK 第一个正式版本 8.0.0-GA 发布已经过去 3 个月了,项目在 Github 上的 stars 继续攀升达到了 1900。今天我们带来了最新版本 8.1.1-GA 的发布,包含了全新的特性和更新。详情见下文。 龙井 8.1.1-GA 的新变化新版本里我们同步了 OpenJDK 上游社区 jdk8u222-ga 的最新更新,带来了上游稳定版本的最新安全更新和补丁。 在 8.0.0-GA 发布的时候,我们介绍了 Dragonwell 第三个新特性 ElasticHeap 的一些情况,很多用户已经跃跃欲试了,这次发布我们带来了正式的 feature:G1ElasticHeap。能够在不影响 Java 业务运行的前提下,动态节约 Java 进程物理内存。 另外,我们还发布了用户期待的 Windows 实验版本 Experimental Windows version,使用 Windows 开发的小伙伴们可以更加方便的使用 Dragonwell JDK 进行相应的开发工作。 G1ElasticHeap从 feature 的名字上我们可以看到 ElasticHeap 是基于 G1 GC 开发的,所以想要使用这个功能的小伙伴,需要开启 G1 GC(-XX:+UseG1GC)。在 8.0.0-GA 正式版介绍时,我们介绍了部分技术背景,由于 Java 自动管理内存的特性,整个 Java Heap 的地址空间和物理内存将被 Java 进程占用,即使使用率不高,回收后也并不会归还给操作系统,导致 Java 进程会有较高的常驻内存。 ...

October 17, 2019 · 2 min · jiezi

Java-字符串-split-踩坑记

1.1 split 的坑前几天在公司对通过 FTP 方式上传的数据文件按照事先规定的格式进行解析后入库,代码的大概实现思路是这样的:先使用流进行文件读取,对文件的每一行数据解析封装成一个个对象,然后进行入库操作。本以为很简单的一个操作,然后写完代码后自己测试发现对文件的每一行进行字符串分割的时候存在问题,在这里做个简单的记录总结。在 Java 中使用 split 方法对字符串进行分割是经常使用的方法,经常在一些文本处理、字符串分割的逻辑中,需要按照一定的分隔符进行分割拆解。这样的功能,大多数情况下我们都会使用 String 中的 split 方法。关于这个方法,稍不注意很容易踩坑。 (1)split 的参数是正则表达式首先一个常见的问题,就是忘记了 String 的 split 方法的参数不是普通的字符串,而是正则表达式,例如下面的这两种使用方式都达不到我们的预期: /** * @author mghio * @date: 2019-10-13 * @version: 1.0 * @description: Java 字符串 split 踩坑记 * @since JDK 1.8 */ public class JavaStringSplitTests { @Test public void testStringSplitRegexArg() { System.out.println(Arrays.toString("m.g.h.i.o".split("."))); System.out.println(Arrays.toString("m|g|h|i|o".split("|"))); } }<!-- more --> 以上代码的结果输出为: [][m, |, g, |, h, |, i, |, o]上面出错的原因是因为 . 和 | 都是正则表达式,应该用转义字符进行处理: ...

October 14, 2019 · 4 min · jiezi

深入理解-Java-中-SPI-机制

本文首发于 vivo互联网技术 微信公众号  链接:https://mp.weixin.qq.com/s/vpy5DJ-hhn0iOyp747oL5A 作者:姜柱SPI(Service Provider Interface),是JDK内置的一种服务提供发现机制,本文由浅入深地介绍了Java SPI机制。 一、简介SPI(Service Provider Interface),是JDK内置的一种服务提供发现机制,可以用来启用框架扩展和替换组件,主要是被框架的开发人员使用,比如java.sql.Driver接口,其他不同厂商可以针对同一接口做出不同的实现,MySQL和PostgreSQL都有不同的实现提供给用户,而Java的SPI机制可以为某个接口寻找服务实现。Java中SPI机制主要思想是将装配的控制权移到程序之外,在模块化设计中这个机制尤其重要,其核心思想就是解耦。 SPI与API区别: API是调用并用于实现目标的类、接口、方法等的描述;SPI是扩展和实现以实现目标的类、接口、方法等的描述;换句话说,API 为操作提供特定的类、方法,SPI 通过操作来符合特定的类、方法。 参考:https://stackoverflow.com/questions/2954372/difference-between-spi-and-api?answertab=votes#tab-topSPI整体机制图如下: 当服务的提供者提供了一种接口的实现之后,需要在classpath下的META-INF/services/目录里创建一个以服务接口命名的文件,这个文件里的内容就是这个接口的具体的实现类。当其他的程序需要这个服务的时候,就可以通过查找这个jar包(一般都是以jar包做依赖)的META-INF/services/中的配置文件,配置文件中有接口的具体实现类名,可以根据这个类名进行加载实例化,就可以使用该服务了。JDK中查找服务的实现的工具类是:java.util.ServiceLoader。 二、应用场景SPI扩展机制应用场景有很多,比如Common-Logging,JDBC,Dubbo等等。 SPI流程: 有关组织和公式定义接口标准第三方提供具体实现: 实现具体方法, 配置 META-INF/services/${interface_name} 文件开发者使用比如JDBC场景下: 首先在Java中定义了接口java.sql.Driver,并没有具体的实现,具体的实现都是由不同厂商提供。在MySQL的jar包mysql-connector-java-6.0.6.jar中,可以找到META-INF/services目录,该目录下会有一个名字为java.sql.Driver的文件,文件内容是com.mysql.cj.jdbc.Driver,这里面的内容就是针对Java中定义的接口的实现。同样在PostgreSQL的jar包PostgreSQL-42.0.0.jar中,也可以找到同样的配置文件,文件内容是org.postgresql.Driver,这是PostgreSQL对Java的java.sql.Driver的实现。三、使用demo1.定义一个接口HelloSPI。 package com.vivo.study.spidemo.spi;public interface HelloSPI { void sayHello();}2.完成接口的多个实现。 package com.vivo.study.spidemo.spi.impl;import com.vivo.study.spidemo.spi.HelloSPI;public class ImageHello implements HelloSPI { public void sayHello() { System.out.println("Image Hello"); }}package com.vivo.study.spidemo.spi.impl;import com.vivo.study.spidemo.spi.HelloSPI;public class TextHello implements HelloSPI { public void sayHello() { System.out.println("Text Hello"); }}在META-INF/services/目录里创建一个以com.vivo.study.spidemo.spi.HelloSPI的文件,这个文件里的内容就是这个接口的具体的实现类。 具体内容如下: com.vivo.study.spidemo.spi.impl.ImageHellocom.vivo.study.spidemo.spi.impl.TextHello3.使用 ServiceLoader 来加载配置文件中指定的实现 ...

September 9, 2019 · 2 min · jiezi

Linux服务器上下载并安装tomcat

⭐ 我的网站: www.mengyingjie.com ⭐ 下载安装tomcat前,先下载安装JDK:Linux服务器 下载并安装 JDK 1下载tomcat:下载地址 2、上传文件,并解压:(如何向服务器里上传下载文件) tar -zxvf apache-tomcat-9.0.19.tar.gz3、加入tomcat的环境变量(不太熟悉vi操作的可以去学习下)安装完成后需要配置一下环境变量,编辑/etc/profile文件: vi /etc/profile在文件尾部添加如下配置: export CATALINA_HOME=/wocloud/tomcat_cluster/tomcat1/apache-tomcat-9.0.19编辑完成后按esc后输入:wq保存退出,最后一步就是通过source命令重新加载/etc/profile文件,使得修改后的内容在当前shell窗口有效: source /etc/profile4、启动tomcat,进入/wocloud/apache-tomcat-9.0.19/bin(我直接安装在了wocloud目录下,如果安装路径不一样,按照自己的路径)执行:./startup.sh,出现如下图片则启动成功。此时还是不能访问的tomcat主页的。 5、然后我们需要在阿里云服务器管理中开发8080和8009端口。 这个时候可以用你本机上的浏览器访问一下,如果可以访问,跳过第6步。不能访问进行第6步。6、配置防火墙在CentOS 7中引入了一个更强大的防火墙——Firewall。打开firewall systemctl start firewalld我们需要在Firewall中开启8080和8009端口(这里的两个端口是tomcat默认的访问tomcat服务器的端口,如果自己改变了端口,要按照自己修改的端口),也就是将8080和8009端口加入到zone(Firewall的新特性,简单讲它的作用就是定义了网络区域网络连接的可信等级)中。命令如下: firewall-cmd --zone=public --add-port=8080/tcp --permanentfirewall-cmd --zone=public --add-port=8009/tcp --permanent这样就成功的将8081端口加入了public区域中,permanent参数表示永久生效,即重启也不会失效,最后不要忘记更新防火墙规则: firewall-cmd --reloadOK,下面看一下public区域下所有已打开的端口,命令如下: firewall-cmd --zone=public --list-ports7、这个时候,就可以通过服务器的外网ip或者域名来访问tomcat了.遇到此类问题,但看了文章还是未解决,评论或加 QQ:781378815

September 8, 2019 · 1 min · jiezi

全栈之路JAVA基础课程十一JDK8十大新特性20190706v12

欢迎进入JAVA基础课程 博客地址:https://blog.csdn.net/houjiyu...本系列文章将主要针对JAVA一些基础知识点进行讲解,为平时归纳所总结,不管是刚接触JAVA开发菜鸟还是业界资深人士,都希望对广大同行带来一些帮助。若有问题请及时留言或加QQ:243042162。 寄语:每个人都有潜在的能量,只不过很容易被习惯掩盖,被时间迷离,被惰性所消磨。十大新特性1.Lambda表达式public class JDK8_features { public List<Integer> list = Lists.newArrayList(1,2,3,4,5,6,7,8,9,10); /** * 1.Lambda表达式 */ @Test public void testLambda(){ list.forEach(System.out::println); list.forEach(e -> System.out.println("方式二:"+e)); }}2.Stream函数式操作流元素集合/** * 2.Stream函数式操作流元素集合 */ @Test public void testStream(){ List<Integer> nums = Lists.newArrayList(1,1,null,2,3,4,null,5,6,7,8,9,10); System.out.println("求和:"+nums .stream()//转成Stream .filter(team -> team!=null)//过滤 .distinct()//去重 .mapToInt(num->num*2)//map操作 .skip(2)//跳过前2个元素 .limit(4)//限制取前4个元素 .peek(System.out::println)//流式处理对象函数 .sum());// }3.接口新增:默认方法与静态方法 /** * 3.接口新增:默认方法与静态方法 * default 接口默认实现方法是为了让集合类默认实现这些函数式处理,而不用修改现有代码 * (List继承于Iterable<T>,接口默认方法不必须实现default forEach方法) */ @Test public void testDefaultFunctionInterface(){ //可以直接使用接口名.静态方法来访问接口中的静态方法 JDK8Interface1.staticMethod(); //接口中的默认方法必须通过它的实现类来调用 new JDK8InterfaceImpl1().defaultMethod(); //多实现类,默认方法重名时必须复写 new JDK8InterfaceImpl2().defaultMethod(); } public class JDK8InterfaceImpl1 implements JDK8Interface1 { //实现接口后,因为默认方法不是抽象方法,重写/不重写都成!// @Override// public void defaultMethod(){// System.out.println("接口中的默认方法");// } } public class JDK8InterfaceImpl2 implements JDK8Interface1,JDK8Interface2 { //实现接口后,默认方法名相同,必须复写默认方法 @Override public void defaultMethod() { //接口的 JDK8Interface1.super.defaultMethod(); System.out.println("实现类复写重名默认方法!!!!"); } }4.方法引用,与Lambda表达式联合使用 @Test public void testMethodReference(){ //构造器引用。语法是Class::new,或者更一般的Class< T >::new,要求构造器方法是没有参数; final Car car = Car.create( Car::new ); final List< Car > cars = Arrays.asList( car ); //静态方法引用。语法是Class::static_method,要求接受一个Class类型的参数; cars.forEach( Car::collide ); //任意对象的方法引用。它的语法是Class::method。无参,所有元素调用; cars.forEach( Car::repair ); //特定对象的方法引用,它的语法是instance::method。有参,在某个对象上调用方法,将列表元素作为参数传入; final Car police = Car.create( Car::new ); cars.forEach( police::follow ); } public static class Car { public static Car create( final Supplier< Car > supplier ) { return supplier.get(); } public static void collide( final Car car ) { System.out.println( "静态方法引用 " + car.toString() ); } public void repair() { System.out.println( "任意对象的方法引用 " + this.toString() ); } public void follow( final Car car ) { System.out.println( "特定对象的方法引用 " + car.toString() ); } }5.引入重复注解 @Test public void RepeatingAnnotations(){ RepeatingAnnotations.main(null); }6.类型注解 @Test public void ElementType(){ Annotations.main(null); } 7.最新的Date/Time API (JSR 310) @Test public void DateTime(){ //1.Clock final Clock clock = Clock.systemUTC(); System.out.println( clock.instant() ); System.out.println( clock.millis() ); //2. ISO-8601格式且无时区信息的日期部分 final LocalDate date = LocalDate.now(); final LocalDate dateFromClock = LocalDate.now( clock ); System.out.println( date ); System.out.println( dateFromClock ); // ISO-8601格式且无时区信息的时间部分 final LocalTime time = LocalTime.now(); final LocalTime timeFromClock = LocalTime.now( clock ); System.out.println( time ); System.out.println( timeFromClock ); // 3.ISO-8601格式无时区信息的日期与时间 final LocalDateTime datetime = LocalDateTime.now(); final LocalDateTime datetimeFromClock = LocalDateTime.now( clock ); System.out.println( datetime ); System.out.println( datetimeFromClock ); // 4.特定时区的日期/时间, final ZonedDateTime zonedDatetime = ZonedDateTime.now(); final ZonedDateTime zonedDatetimeFromClock = ZonedDateTime.now( clock ); final ZonedDateTime zonedDatetimeFromZone = ZonedDateTime.now( ZoneId.of( "America/Los_Angeles" ) ); System.out.println( zonedDatetime ); System.out.println( zonedDatetimeFromClock ); System.out.println( zonedDatetimeFromZone ); //5.在秒与纳秒级别上的一段时间 final LocalDateTime from = LocalDateTime.of( 2014, Month.APRIL, 16, 0, 0, 0 ); final LocalDateTime to = LocalDateTime.of( 2015, Month.APRIL, 16, 23, 59, 59 ); final Duration duration = Duration.between( from, to ); System.out.println( "Duration in days: " + duration.toDays() ); System.out.println( "Duration in hours: " + duration.toHours() ); } 8.新增base64加解密API @Test public void testBase64(){ final String text = "就是要测试加解密!!abjdkhdkuasu!!@@@@"; String encoded = Base64.getEncoder() .encodeToString( text.getBytes( StandardCharsets.UTF_8 ) ); System.out.println("加密后="+ encoded ); final String decoded = new String( Base64.getDecoder().decode( encoded ), StandardCharsets.UTF_8 ); System.out.println( "解密后="+decoded ); }9.数组并行(parallel)操作 @Test public void testParallel(){ long[] arrayOfLong = new long [ 20000 ]; //1.给数组随机赋值 Arrays.parallelSetAll( arrayOfLong, index -> ThreadLocalRandom.current().nextInt( 1000000 ) ); //2.打印出前10个元素 Arrays.stream( arrayOfLong ).limit( 10 ).forEach( i -> System.out.print( i + " " ) ); System.out.println(); //3.数组排序 Arrays.parallelSort( arrayOfLong ); //4.打印排序后的前10个元素 Arrays.stream( arrayOfLong ).limit( 10 ).forEach( i -> System.out.print( i + " " ) ); System.out.println(); } 10.JVM的PermGen空间被移除:取代它的是Metaspace(JEP 122)元空间 @Test public void testMetaspace(){ //-XX:MetaspaceSize初始空间大小,达到该值就会触发垃圾收集进行类型卸载,同时GC会对该值进行调整 //-XX:MaxMetaspaceSize最大空间,默认是没有限制 //-XX:MinMetaspaceFreeRatio在GC之后,最小的Metaspace剩余空间容量的百分比,减少为分配空间所导致的垃圾收集 //-XX:MaxMetaspaceFreeRatio在GC之后,最大的Metaspace剩余空间容量的百分比,减少为释放空间所导致的垃圾收集 }参考网站:(1)https://www.cnblogs.com/suger...(2)https://blog.csdn.net/xuspcsd... ...

July 7, 2019 · 3 min · jiezi

Java系列之泛型

自从 JDK 1.5 提供了泛型概念,泛型使得开发者可以定义较为安全的类型,不至于强制类型转化时出现类型转化异常,在没有反省之前,可以通过 Object 来完成不同类型数据之间的操作,但是强制类型转换(向下转型)在不确定具体类型的情况下会出错,泛型机制的引入就是解决数据类型不明确 的问题。 定义泛型类定义一个泛型类,语法如下: //定义泛型类class 类名<T>{ }其中,T 表示一个类型的名称,T 可以表示成其他名称,一般习惯写成 T,<> 里面的类型可以有多个,中间以逗号隔开,下面是一个泛型类,具体如下: /** * 定义泛型类 * @author jzman * @param <T> */public class GenercityClass<T1,T2> { private T1 score; private T2 desc; public GenercityClass() {} public GenercityClass(T1 score, T2 desc) { this.score = score; this.desc = desc; } public T1 getScore() { return score; } public void setScore(T1 score) { this.score = score; } public T2 getDesc() { return desc; } public void setDesc(T2 desc) { this.desc = desc; } public static void main(String[] args) { //使用时指定具体类型,具体类型只能是引用类型,不能时基本类型,如 int GenercityClass<Integer, String> genercity = new GenercityClass<>(90,"A"); int score = genercity.getScore(); String desc = genercity.getDesc(); System.out.println("score="+score+",desc="+desc); }}显然,使用泛型定义的类可以在使用时根据不同的需求指定 <T1,T2> 所代表的真实类型,这样就不会有类型转换操作,将不会出现 ClassCastException 异常,编译器会提前检查类型是否匹配,下面这样会出错,具体如下: ...

June 10, 2019 · 4 min · jiezi

初读Java并发编程的艺术第十章Executor框架-101-Executor框架简介

在java中,直接使用线程来异步的执行任务,线程的每次创建与销毁需要一定的计算机资源开销。每个任务创建一个线程的话,当任务数量多的时候,则对应的创建销毁开销会消耗大量的资源,这种策略最终可能会使处于高负荷状态的应用崩溃。 Java中的线程,即使工作单元,也是执行机制。从JDK5开始,把工作单元与执行机制分离开来。 工作单元:Runnable 和 Callable执行机制:Executor 框架1. Executor 框架简介1.1 Executor 框架的两级调度模型在HotSpot VM 的线程模型中,Java线程(java.lang.Thread) 被一对一的映射为本地操作系统的线程。Java线程的启动与销毁都与本地线程同步。操作系统会调度所有线程并将它们分配给可用的CPU。在上层,Java使用多线程的程序,通常会将应用分解为若干任务,然后使用用户级别的调度器(Executor框架)将这些任务映射为对应数量的线程;底层,操作系统会将这些线程映射到硬件处理器上,切下层硬件的调度并不受应用程序的控制。调度模型如下图 1.2 Executor框架的结构与成员1. Excutor 框架的结构 -主要由3大部分组成任务 Runnable接口(无返回值)Callable<V>接口(有返回值)任务的执行 执行机制的核心接口-Executor,以及实现Executor接口的ExecutorService, Executor框架 中有两个关键类实现了ExecutorService: ThreadPoolExecutor 线程池的实践类,执行被提交的线程、任务(Callable/Runnable 接口的实现类中的run()方法)ScheduledThreadPoolExecutor 给定延迟或定期的执行任务(Callable/Runnable 接口的实现类中的run()方法)、命令。比Timer 更加灵活,强大。异步执行的结果(返回值) Future 接口 可以通过get()方法或者异步执行的结果FutureTask<V>类 (实现了Future接口) Executor框架的使用: 主线程(main线程)创建实现Runnable或者Callable<V> 接口的待执行任务对象。Executors可以将Runnable封装为Callable<V> {Executors.callable(Runnable task)/(Runnable task,result)}。Runnable接口对象可以交由ExexutorService执行 {ExecutorService.executor(Runnable r) {无返回值};或者把Runnable接口对象或Callable<V>接口对象交由ExecutorService执行 {ExecutorService.submit(Runnable r/Callable<V> t) 有返回值 Futrue接口的对象,现阶段JDK返回的是FutureTask};最后,主线程(main线程)执行 FutrueTask.get()阻塞,等待任务执行完成,同时获取返回值。也可以执行FutureTask.cancel(boolean mayInterruptIfRunning)取消执行(参数表示如果正在执行是否取消)。2. Executor框架的成员主要成员: ThreadPoolExecutor(线程池)、ScheduldThreadPoolExecutor、Runnable接口、Future<V>接口、Callable<V>接口 以及 Executors工具类。ThreadPoolExecutor 通常使用Executors 创建,Executors可以创建三种类型的ThreadPoolExecutor:SingleThreadExecuto、FixedThreadPool、CachedThreadPool FixedThreadPool 创建固定线程数,适用于限制当前线程数量时,适用于负载较重的服务器。 Executor创建使用的API: public static ExecutorService newFixedThreadPool(int nThreads);public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory);SingleThreadExecutor 创建单个线程,任意时间点不会有多个线程是活动的,适用于需要保证顺序执行各任务的时候。 Executors创建API: ...

May 7, 2019 · 1 min · jiezi

mac环境下切换jdk版本

打开终端 cdvim .bash_profile输入以下 export JAVA_7_HOME=`/usr/libexec/java_home -v 1.7`export JAVA_8_HOME=`/usr/libexec/java_home -v 1.8`export JAVA_HOME=$JAVA_8_HOMEalias jdk7="export JAVA_HOME=$JAVA_7_HOME"alias jdk8="export JAVA_HOME=$JAVA_8_HOME"Mac OSX 10.5+ 以后,官方建议$JAVA_HOME的设置用 /usr/libexec/java_home 代替也可以写绝对路径,通过echo $JAVA_HOME 查看JDK路径例如 export JAVA_7_HOME="/Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk/Contents/Home"export JAVA_8_HOME="/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home"修改完成后,保存重新编译 source ~/.bash_profile在终端中输入jdk7、jdk8 切换版本,通过java -version 查看版本

April 29, 2019 · 1 min · jiezi

Java-队列

引言本周在编写短信验证码频率限制切面的时候,经潘老师给的实现思路,使用队列进行实现。 看了看java.util包下的Queue接口,发现还从来没用过呢! Collection集合类接口,由它派生出List、Set和Queue,Map属于另一个独立的接口,和Collection没有继承关系。 List、Set和Map我们用的都是已经相当熟练了,今天,我们就来盘这个队列Queue! 探索队列与栈都是数据结构的基础话题,队列:先进先出;栈:后进先出。 方法Queue接口中声明了六个方法,分成三对来使用。 入队操作 方法特点建议add入队失败抛出异常 offer入队失败返回false推荐出队操作 方法特点建议remove出队失败抛出异常 poll出队失败返回null推荐取队头操作 方法特点建议element队列为空时抛出异常 peek队列为空时返回null推荐PriorityQueue在java.util包中,除抽象类外,直接实现Queue接口的只有PriorityQueue优先级队列。 优先级队列比普通的队列要高级,普通的队列如果是先进的肯定是在队头的,而优先级队列根据优先级判断当前队头元素是什么。很适合实现操作系统中的按优先级实现进程调度。 如果需要使用优先级队列进行排序时,需要传入比较器。 该队列使用数组实现,线程不安全。 Deque java.util包中,Deque接口继承Queue接口。 Deque:double-ended queue,双端队列。 双端队列,相比普通队列就是可操作两端,有两个队头,也有两个队尾。 所以再去看Deque接口中声明的方法,都是两套的。offerFirst、offerLast、pollFirst、pollLast等。 所以说,如果使用双端队列,不仅可以当队列用,也可以当栈用,因为可以自己控制出的是队头还是队尾。 Deque有两个实现类:ArrayDeque和LinkedList。 原来LinkedList不仅实现了List接口,还实现了Deque接口。 两者的区别显而易见,一个是数组方式实现的,一个是链表的方式实现的。 TODO这些都是java.util包下的,都是线程不安全的实现,JDK所有线程安全的队列实现都在java.util.concurrent包下,也就是阻塞队列,以后再完善。

April 27, 2019 · 1 min · jiezi

聊聊Java 9的Compact Strings

序本文主要研究一下Java 9的Compact StringsCompressed Strings(Java 6)Java 6引入了Compressed Strings,对于one byte per character使用byte[],对于two bytes per character继续使用char[];之前可以使用-XX:+UseCompressedStrings来开启,不过在java7被废弃了,然后在java8被移除Compact Strings(Java 9)Java 9引入了Compact Strings来取代Java 6的Compressed Strings,它的实现更过彻底,完全使用byte[]来替代char[],同时新引入了一个字段coder来标识是LATIN1还是UTF16Stringjava.base/java/lang/String.javapublic final class String implements java.io.Serializable, Comparable<String>, CharSequence, Constable, ConstantDesc { /** * The value is used for character storage. * * @implNote This field is trusted by the VM, and is a subject to * constant folding if String instance is constant. Overwriting this * field after construction will cause problems. * * Additionally, it is marked with {@link Stable} to trust the contents * of the array. No other facility in JDK provides this functionality (yet). * {@link Stable} is safe here, because value is never null. / @Stable private final byte[] value; /* * The identifier of the encoding used to encode the bytes in * {@code value}. The supported values in this implementation are * * LATIN1 * UTF16 * * @implNote This field is trusted by the VM, and is a subject to * constant folding if String instance is constant. Overwriting this * field after construction will cause problems. / private final byte coder; /* Cache the hash code for the string / private int hash; // Default to 0 /* use serialVersionUID from JDK 1.0.2 for interoperability / private static final long serialVersionUID = -6849794470754667710L; /* * If String compaction is disabled, the bytes in {@code value} are * always encoded in UTF16. * * For methods with several possible implementation paths, when String * compaction is disabled, only one code path is taken. * * The instance field value is generally opaque to optimizing JIT * compilers. Therefore, in performance-sensitive place, an explicit * check of the static boolean {@code COMPACT_STRINGS} is done first * before checking the {@code coder} field since the static boolean * {@code COMPACT_STRINGS} would be constant folded away by an * optimizing JIT compiler. The idioms for these cases are as follows. * * For code such as: * * if (coder == LATIN1) { … } * * can be written more optimally as * * if (coder() == LATIN1) { … } * * or: * * if (COMPACT_STRINGS && coder == LATIN1) { … } * * An optimizing JIT compiler can fold the above conditional as: * * COMPACT_STRINGS == true => if (coder == LATIN1) { … } * COMPACT_STRINGS == false => if (false) { … } * * @implNote * The actual value for this field is injected by JVM. The static * initialization block is used to set the value here to communicate * that this static final field is not statically foldable, and to * avoid any possible circular dependency during vm initialization. / static final boolean COMPACT_STRINGS; static { COMPACT_STRINGS = true; } /* * Class String is special cased within the Serialization Stream Protocol. * * A String instance is written into an ObjectOutputStream according to * <a href="{@docRoot}/../specs/serialization/protocol.html#stream-elements"> * Object Serialization Specification, Section 6.2, “Stream Elements”</a> / private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0]; /* * Initializes a newly created {@code String} object so that it represents * an empty character sequence. Note that use of this constructor is * unnecessary since Strings are immutable. / public String() { this.value = “".value; this.coder = “".coder; } //…… public char charAt(int index) { if (isLatin1()) { return StringLatin1.charAt(value, index); } else { return StringUTF16.charAt(value, index); } } public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String aString = (String)anObject; if (coder() == aString.coder()) { return isLatin1() ? StringLatin1.equals(value, aString.value) : StringUTF16.equals(value, aString.value); } } return false; } public int compareTo(String anotherString) { byte v1[] = value; byte v2[] = anotherString.value; if (coder() == anotherString.coder()) { return isLatin1() ? StringLatin1.compareTo(v1, v2) : StringUTF16.compareTo(v1, v2); } return isLatin1() ? StringLatin1.compareToUTF16(v1, v2) : StringUTF16.compareToLatin1(v1, v2); } public int hashCode() { int h = hash; if (h == 0 && value.length > 0) { hash = h = isLatin1() ? StringLatin1.hashCode(value) : StringUTF16.hashCode(value); } return h; } public int indexOf(int ch, int fromIndex) { return isLatin1() ? StringLatin1.indexOf(value, ch, fromIndex) : StringUTF16.indexOf(value, ch, fromIndex); } public String substring(int beginIndex) { if (beginIndex < 0) { throw new StringIndexOutOfBoundsException(beginIndex); } int subLen = length() - beginIndex; if (subLen < 0) { throw new StringIndexOutOfBoundsException(subLen); } if (beginIndex == 0) { return this; } return isLatin1() ? StringLatin1.newString(value, beginIndex, subLen) : StringUTF16.newString(value, beginIndex, subLen); } //…… byte coder() { return COMPACT_STRINGS ? coder : UTF16; } byte[] value() { return value; } private boolean isLatin1() { return COMPACT_STRINGS && coder == LATIN1; } @Native static final byte LATIN1 = 0; @Native static final byte UTF16 = 1; //……}COMPACT_STRINGS默认为true,即该特性默认是开启的coder方法判断COMPACT_STRINGS为true的话,则返回coder值,否则返回UTF16;isLatin1方法判断COMPACT_STRINGS为true且coder为LATIN1则返回true诸如charAt、equals、hashCode、indexOf、substring等等一系列方法都依赖isLatin1方法来区分对待是StringLatin1还是StringUTF16StringConcatFactory实例public class Java9StringDemo { public static void main(String[] args){ String stringLiteral = “tom”; String stringObject = stringLiteral + “cat”; }}这段代码stringObject由变量stringLiteral及cat拼接而来javapjavac src/main/java/com/example/javac/Java9StringDemo.javajavap -v src/main/java/com/example/javac/Java9StringDemo.class Last modified 2019年4月7日; size 770 bytes MD5 checksum fecfca9c829402c358c4d5cb948004ff Compiled from “Java9StringDemo.java"public class com.example.javac.Java9StringDemo minor version: 0 major version: 56 flags: (0x0021) ACC_PUBLIC, ACC_SUPER this_class: #4 // com/example/javac/Java9StringDemo super_class: #5 // java/lang/Object interfaces: 0, fields: 0, methods: 2, attributes: 3Constant pool: #1 = Methodref #5.#14 // java/lang/Object."<init>”:()V #2 = String #15 // tom #3 = InvokeDynamic #0:#19 // #0:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String; #4 = Class #20 // com/example/javac/Java9StringDemo #5 = Class #21 // java/lang/Object #6 = Utf8 <init> #7 = Utf8 ()V #8 = Utf8 Code #9 = Utf8 LineNumberTable #10 = Utf8 main #11 = Utf8 ([Ljava/lang/String;)V #12 = Utf8 SourceFile #13 = Utf8 Java9StringDemo.java #14 = NameAndType #6:#7 // “<init>”:()V #15 = Utf8 tom #16 = Utf8 BootstrapMethods #17 = MethodHandle 6:#22 // REF_invokeStatic java/lang/invoke/StringConcatFactory.makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite; #18 = String #23 // \u0001cat #19 = NameAndType #24:#25 // makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String; #20 = Utf8 com/example/javac/Java9StringDemo #21 = Utf8 java/lang/Object #22 = Methodref #26.#27 // java/lang/invoke/StringConcatFactory.makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite; #23 = Utf8 \u0001cat #24 = Utf8 makeConcatWithConstants #25 = Utf8 (Ljava/lang/String;)Ljava/lang/String; #26 = Class #28 // java/lang/invoke/StringConcatFactory #27 = NameAndType #24:#32 // makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite; #28 = Utf8 java/lang/invoke/StringConcatFactory #29 = Class #34 // java/lang/invoke/MethodHandles$Lookup #30 = Utf8 Lookup #31 = Utf8 InnerClasses #32 = Utf8 (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite; #33 = Class #35 // java/lang/invoke/MethodHandles #34 = Utf8 java/lang/invoke/MethodHandles$Lookup #35 = Utf8 java/lang/invoke/MethodHandles{ public com.example.javac.Java9StringDemo(); descriptor: ()V flags: (0x0001) ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>”:()V 4: return LineNumberTable: line 8: 0 public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=3, args_size=1 0: ldc #2 // String tom 2: astore_1 3: aload_1 4: invokedynamic #3, 0 // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String; 9: astore_2 10: return LineNumberTable: line 11: 0 line 12: 3 line 13: 10}SourceFile: “Java9StringDemo.java"InnerClasses: public static final #30= #29 of #33; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandlesBootstrapMethods: 0: #17 REF_invokeStatic java/lang/invoke/StringConcatFactory.makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite; Method arguments: #18 \u0001catjavap之后可以看到通过Java 9利用InvokeDynamic调用了StringConcatFactory.makeConcatWithConstants方法进行字符串拼接优化;而Java 8则是通过转换为StringBuilder来进行优化StringConcatFactory.makeConcatWithConstantsjava.base/java/lang/invoke/StringConcatFactory.javapublic final class StringConcatFactory { //…… /* * Concatenation strategy to use. See {@link Strategy} for possible options. * This option is controllable with -Djava.lang.invoke.stringConcat JDK option. / private static Strategy STRATEGY; /* * Default strategy to use for concatenation. / private static final Strategy DEFAULT_STRATEGY = Strategy.MH_INLINE_SIZED_EXACT; private enum Strategy { /* * Bytecode generator, calling into {@link java.lang.StringBuilder}. / BC_SB, /* * Bytecode generator, calling into {@link java.lang.StringBuilder}; * but trying to estimate the required storage. / BC_SB_SIZED, /* * Bytecode generator, calling into {@link java.lang.StringBuilder}; * but computing the required storage exactly. / BC_SB_SIZED_EXACT, /* * MethodHandle-based generator, that in the end calls into {@link java.lang.StringBuilder}. * This strategy also tries to estimate the required storage. / MH_SB_SIZED, /* * MethodHandle-based generator, that in the end calls into {@link java.lang.StringBuilder}. * This strategy also estimate the required storage exactly. / MH_SB_SIZED_EXACT, /* * MethodHandle-based generator, that constructs its own byte[] array from * the arguments. It computes the required storage exactly. */ MH_INLINE_SIZED_EXACT } static { // In case we need to double-back onto the StringConcatFactory during this // static initialization, make sure we have the reasonable defaults to complete // the static initialization properly. After that, actual users would use // the proper values we have read from the properties. STRATEGY = DEFAULT_STRATEGY; // CACHE_ENABLE = false; // implied // CACHE = null; // implied // DEBUG = false; // implied // DUMPER = null; // implied Properties props = GetPropertyAction.privilegedGetProperties(); final String strategy = props.getProperty(“java.lang.invoke.stringConcat”); CACHE_ENABLE = Boolean.parseBoolean( props.getProperty(“java.lang.invoke.stringConcat.cache”)); DEBUG = Boolean.parseBoolean( props.getProperty(“java.lang.invoke.stringConcat.debug”)); final String dumpPath = props.getProperty(“java.lang.invoke.stringConcat.dumpClasses”); STRATEGY = (strategy == null) ? DEFAULT_STRATEGY : Strategy.valueOf(strategy); CACHE = CACHE_ENABLE ? new ConcurrentHashMap<>() : null; DUMPER = (dumpPath == null) ? null : ProxyClassesDumper.getInstance(dumpPath); } public static CallSite makeConcatWithConstants(MethodHandles.Lookup lookup, String name, MethodType concatType, String recipe, Object… constants) throws StringConcatException { if (DEBUG) { System.out.println(“StringConcatFactory " + STRATEGY + " is here for " + concatType + “, {” + recipe + “}, " + Arrays.toString(constants)); } return doStringConcat(lookup, name, concatType, false, recipe, constants); } private static CallSite doStringConcat(MethodHandles.Lookup lookup, String name, MethodType concatType, boolean generateRecipe, String recipe, Object… constants) throws StringConcatException { Objects.requireNonNull(lookup, “Lookup is null”); Objects.requireNonNull(name, “Name is null”); Objects.requireNonNull(concatType, “Concat type is null”); Objects.requireNonNull(constants, “Constants are null”); for (Object o : constants) { Objects.requireNonNull(o, “Cannot accept null constants”); } if ((lookup.lookupModes() & MethodHandles.Lookup.PRIVATE) == 0) { throw new StringConcatException(“Invalid caller: " + lookup.lookupClass().getName()); } int cCount = 0; int oCount = 0; if (generateRecipe) { // Mock the recipe to reuse the concat generator code char[] value = new char[concatType.parameterCount()]; Arrays.fill(value, TAG_ARG); recipe = new String(value); oCount = concatType.parameterCount(); } else { Objects.requireNonNull(recipe, “Recipe is null”); for (int i = 0; i < recipe.length(); i++) { char c = recipe.charAt(i); if (c == TAG_CONST) cCount++; if (c == TAG_ARG) oCount++; } } if (oCount != concatType.parameterCount()) { throw new StringConcatException( “Mismatched number of concat arguments: recipe wants " + oCount + " arguments, but signature provides " + concatType.parameterCount()); } if (cCount != constants.length) { throw new StringConcatException( “Mismatched number of concat constants: recipe wants " + cCount + " constants, but only " + constants.length + " are passed”); } if (!concatType.returnType().isAssignableFrom(String.class)) { throw new StringConcatException( “The return type should be compatible with String, but it is " + concatType.returnType()); } if (concatType.parameterSlotCount() > MAX_INDY_CONCAT_ARG_SLOTS) { throw new StringConcatException(“Too many concat argument slots: " + concatType.parameterSlotCount() + “, can only accept " + MAX_INDY_CONCAT_ARG_SLOTS); } String className = getClassName(lookup.lookupClass()); MethodType mt = adaptType(concatType); Recipe rec = new Recipe(recipe, constants); MethodHandle mh; if (CACHE_ENABLE) { Key key = new Key(className, mt, rec); mh = CACHE.get(key); if (mh == null) { mh = generate(lookup, className, mt, rec); CACHE.put(key, mh); } } else { mh = generate(lookup, className, mt, rec); } return new ConstantCallSite(mh.asType(concatType)); } private static MethodHandle generate(Lookup lookup, String className, MethodType mt, Recipe recipe) throws StringConcatException { try { switch (STRATEGY) { case BC_SB: return BytecodeStringBuilderStrategy.generate(lookup, className, mt, recipe, Mode.DEFAULT); case BC_SB_SIZED: return BytecodeStringBuilderStrategy.generate(lookup, className, mt, recipe, Mode.SIZED); case BC_SB_SIZED_EXACT: return BytecodeStringBuilderStrategy.generate(lookup, className, mt, recipe, Mode.SIZED_EXACT); case MH_SB_SIZED: return MethodHandleStringBuilderStrategy.generate(mt, recipe, Mode.SIZED); case MH_SB_SIZED_EXACT: return MethodHandleStringBuilderStrategy.generate(mt, recipe, Mode.SIZED_EXACT); case MH_INLINE_SIZED_EXACT: return MethodHandleInlineCopyStrategy.generate(mt, recipe); default: throw new StringConcatException(“Concatenation strategy " + STRATEGY + " is not implemented”); } } catch (Error | StringConcatException e) { // Pass through any error or existing StringConcatException throw e; } catch (Throwable t) { throw new StringConcatException(“Generator failed”, t); } } //……}makeConcatWithConstants方法内部调用了doStringConcat,而doStringConcat方法则调用了generate方法来生成MethodHandle;generate根据不同的STRATEGY来生成MethodHandle,这些STRATEGY有BC_SB、BC_SB_SIZED、BC_SB_SIZED_EXACT、MH_SB_SIZED、MH_SB_SIZED_EXACT、MH_INLINE_SIZED_EXACT,默认是MH_INLINE_SIZED_EXACT(可以通过-Djava.lang.invoke.stringConcat来改变默认的策略)小结Java 9引入了Compact Strings来取代Java 6的Compressed Strings,它的实现更过彻底,完全使用byte[]来替代char[],同时新引入了一个字段coder来标识是LATIN1还是UTF16isLatin1方法判断COMPACT_STRINGS为true且coder为LATIN1则返回true;诸如charAt、equals、hashCode、indexOf、substring等等一系列方法都依赖isLatin1方法来区分对待是StringLatin1还是StringUTF16Java 9利用InvokeDynamic调用了StringConcatFactory.makeConcatWithConstants方法进行字符串拼接优化,相比于Java 8通过转换为StringBuilder来进行优化,Java 9提供了多种STRATEGY可供选择,这些STRATEGY有BC_SB(等价于Java 8的优化方式)、BC_SB_SIZED、BC_SB_SIZED_EXACT、MH_SB_SIZED、MH_SB_SIZED_EXACT、MH_INLINE_SIZED_EXACT,默认是MH_INLINE_SIZED_EXACT(可以通过-Djava.lang.invoke.stringConcat来改变默认的策略)docString CompactionJEP 254: Compact StringsJava 9: Compact StringsCompact Strings In Java 9Java 9 Compact Strings ExampleEvolution of Strings in Java to Compact Strings and Indify String Concatenation ...

April 7, 2019 · 9 min · jiezi

Oracle与OpenJDK之间的区别

简介在本文中,我们将探讨Oracle Java Development Kit和OpenJDK之间的差异并进行比较。Oracle JDKOracle JDK由Oracle公司开发,该公司是Sun许可证,基于Java标准版规范实现。它以二进制产品的形式发布。它支持多种操作系统,如Windows,Linux,Solaris,MacOS等。它支持不同的平台,如Intel 32位和64位架构,ARM架构和SPARC。它完全基于Java编程语言。之后,该许可证宣布将根据GPL(通用公共许可证)许可证发布。Oracle JDK包含许多组件作为库形式的编程工具集合。我们来看看Java SE的历史:JDK Beta - 1995JDK 1.0 - 1996年1月JDK 1.1 - 1997年2月J2SE 1.2 - 1998年12月J2SE 1.3 - 2000年5月J2SE 1.4 - 2002年2月J2SE 5.0 - 2004年9月Java SE 6 - 2006年12月Java SE 7 - 2011年7月Java SE 8(LTS) - 2014年3月Java SE 9 - 2017年9月Java SE 10(18.3) - 2018年3月Java SE 11(18.9 LTS) - 2018年9月Java SE 12(19.3) - 2019年3月注意:不再支持斜体版本。我们可以看到Java SE的主要版本大约每两年发布一次,直到Java SE 7.从Java SE 6开始花了五年时间,之后又花了三年时间到达Java SE 8。自Java SE 10以来,我们可以期待每六个月发布一次新版本。但是,并非所有版本都是长期支持(LTS)版本。由于Oracle的发布计划,LTS产品发布仅每三年发布一次。OpenJDKOpenJDK是Java SE平台版的开源和免费实现,它是Sun Corporation(现在的Oracle Corporation)于2006年开始的开发结果。它是根据GNU GPL许可证授权的。它最初于2007年发布。它由Oracle Corporation,Red Hat,IBM,Apple Inc.,OpenJDK和Java Community等开发。它是使用C ++和Java编程语言编写的。它支持不同的操作系统,如FreeBSD,Linux,Microsoft Windows,Mac OS X. OpenJDK是Java SE Platform Edition的官方参考实现。现在让我们看看OpenJDK版本:OpenJDK 6项目 - 基于JDK 7,但经过修改后提供了Java 6的开源版本OpenJDK 7项目 - 2011年7月28日OpenJDK 7u项目 - 该项目开发Java Development Kit 7的更新OpenJDK 8项目 - 2014年3月18日OpenJDK 8u项目 - 该项目开发Java Development Kit 8的更新OpenJDK 9项目 - 2017年9月21日JDK项目于2018年3月10日至20日发布JDK项目于2018年9月11日至25日发布JDK项目发布12 - 稳定阶段Oracle与OpenJDK之间的比较(信息图表)Oracle与OpenJDK之间的主要区别Oracle与OpenJDK都是市场上的热门选择; 让我们讨论一下OracleJDK与OpenJDK之间的一些主要差异:Oracle JDK版本将每三年发布一次,而OpenJDK版本每三个月发布一次。Oracle JDK将更多地关注稳定性,它重视更多的企业级用户,而OpenJDK经常发布以支持其他性能,这可能会导致不稳定。Oracle JDK支持长期发布的更改,而Open JDK仅支持计划和完成下一个发行版。Oracle JDK根据二进制代码许可协议获得许可,而OpenJDK根据GPL v2许可获得许可。使用Oracle平台时会产生一些许可影响。如Oracle 宣布的那样,在没有商业许可的情况下,在2019年1月之后发布的Oracle Java SE 8的公开更新将无法用于商业,商业或生产用途。但是,OpenJDK是完全开源的,可以自由使用。Oracle JDK的构建过程基于OpenJDK,因此OpenJDK与Oracle JDK之间没有技术差异。顶级公司正在使用Oracle JDK,例如Android Studio,Minecraft和IntelliJ IDEA开发工具,其中Open JDK不太受欢迎。Oracle JDK具有Flight Recorder,Java Mission Control和Application Class-Data Sharing功能,Open JDK具有Font Renderer功能,这是OpenJDK与Oracle JDK之间的显着差异。Oracle JDK具有良好的GC选项和更好的渲染器,而OpenJDK具有更少的GC选项,并且由于其包含自己的渲染器的分布,因此具有较慢的图形渲染器选项。在响应性和JVM性能方面,Oracle JDK与OpenJDK相比提供了更好的性能。与OpenJDK相比,Oracle JDK的开源社区较少,OpenJDK社区用户的表现优于Oracle JDK发布的功能,以提高性能。如果使用Oracle JDK会产生许可影响,而OpenJDK没有这样的问题,并且可以以任何方式使用,以满足完全开源和免费使用。Oracle JDK在运行JDK时不会产生任何问题,而OpenJDK在为某些用户运行JDK时会产生一些问题。根据使用方的使用和许可协议,现有应用程序可以从Oracle JDK迁移到Open JDK,反之亦然。Oracle JDK将从其10.0.X版本将收费,用户必须付费或必须依赖OpenJDK才能使用其免费版本。Oracle JDK不会为即将发布的版本提供长期支持,用户每次都必须通过更新到最新版本获得支持来获取最新版本。Oracle JDK以前的1.0版以前的版本是由Sun开发的,后来被Oracle收购并为其他版本维护,而OpenJDK最初只基于Java SDK或JDK版本7。Oracle JDK发布时大多数功能都是开源的,其中一些功能免于开源,并且根据Sun的许可授权,而OpenJDK发布了所有功能,如开源和免费。Oracle JDK完全由Oracle公司开发,而Open JDK项目由IBM,Apple,SAP AG,Redhat等顶级公司加入和合作。Oracle与OpenJDK比较表以下是Oracle与OpenJDK之间最重要的比较:Oracle与OpenJDK之间比较Oracle JDKOpenJDK执照它是根据GPL(通用公共许可证)许可证授权的它是根据GNU GPL(通用公共许可证)许可证授权的发展由Sun Microsystems Inc.开发由Oracle,OpenJDK和Java社区开发性能根据Sun JDK的开发和实现提供性能提供由Oracle JDK之上的一些供应商开发的高性能可扩展性根据Sun的实施可以使用其他库或Oracle JDK进行改进费用Sun的官方执行许可证开源和免费实施可供免费使用速度由Sun Microsystems Inc.开发第三方供应商将通过进行一些调整来提高JVM的速度操作系统支持Windows,Linux,Solaris,MacOSFreeBSD,Linux,Microsoft Windows,Mac OS X.便于使用可以与任何应用程序开发一起使用可以与任何应用程序开发和其他开源工具一起使用,以提高开源实现模型的性能。结论Oracle JDK可用于开发Java Web应用程序,独立应用程序以及许多其他图形用户界面以及其他开发工具。Oracle JDK执行的所有操作或任务也可以由OpenJDK执行,但只有Oracle与OpenJDK之间的区别在于Open JDK在现有Oracle JDK之上的许可和其他工具集成和实现。使用OpenJDK的优点是可以根据应用程序的要求修改性能,可伸缩性和实现,以根据需要调整Java虚拟机。OpenJDK的优势更多,Oracle JDK的使用在Oracle JDK实现中使用的标准方面也有一些好处,这将确保应用程序稳定和良好维护。 ...

April 1, 2019 · 1 min · jiezi

聊聊openjdk的BufferPoolMXBean

序本文主要研究一下openjdk的BufferPoolMXBeanPlatformManagedObjectjava.management/java/lang/management/PlatformManagedObject.javapublic interface PlatformManagedObject { /** * Returns an {@link ObjectName ObjectName} instance representing * the object name of this platform managed object. * * @return an {@link ObjectName ObjectName} instance representing * the object name of this platform managed object. / public ObjectName getObjectName();}PlatformManagedObject接口定义了getObjectName方法用于返回ObjectNameBufferPoolMXBeanjava.management/java/lang/management/BufferPoolMXBean.javapublic interface BufferPoolMXBean extends PlatformManagedObject { /* * Returns the name representing this buffer pool. * * @return The name of this buffer pool. / String getName(); /* * Returns an estimate of the number of buffers in the pool. * * @return An estimate of the number of buffers in this pool / long getCount(); /* * Returns an estimate of the total capacity of the buffers in this pool. * A buffer’s capacity is the number of elements it contains and the value * returned by this method is an estimate of the total capacity of buffers * in the pool in bytes. * * @return An estimate of the total capacity of the buffers in this pool * in bytes / long getTotalCapacity(); /* * Returns an estimate of the memory that the Java virtual machine is using * for this buffer pool. The value returned by this method may differ * from the estimate of the total {@link #getTotalCapacity capacity} of * the buffers in this pool. This difference is explained by alignment, * memory allocator, and other implementation specific reasons. * * @return An estimate of the memory that the Java virtual machine is using * for this buffer pool in bytes, or {@code -1L} if an estimate of * the memory usage is not available / long getMemoryUsed();}BufferPoolMXBean接口继承了PlatformManagedObject,它定义了getName、getCount、getTotalCapacity、getMemoryUsed方法ManagementFactoryHelperjava.management/sun/management/ManagementFactoryHelper.javapublic class ManagementFactoryHelper { static { // make sure that the management lib is loaded within // java.lang.management.ManagementFactory jdk.internal.misc.Unsafe.getUnsafe().ensureClassInitialized(ManagementFactory.class); } private static final VMManagement jvm = new VMManagementImpl(); private ManagementFactoryHelper() {}; public static VMManagement getVMManagement() { return jvm; } static final String LOGGING_MXBEAN_NAME = “java.util.logging:type=Logging”; private static ClassLoadingImpl classMBean = null; private static MemoryImpl memoryMBean = null; private static ThreadImpl threadMBean = null; private static RuntimeImpl runtimeMBean = null; private static CompilationImpl compileMBean = null; private static BaseOperatingSystemImpl osMBean = null; //…… private static List<BufferPoolMXBean> bufferPools = null; public static synchronized List<BufferPoolMXBean> getBufferPoolMXBeans() { if (bufferPools == null) { bufferPools = new ArrayList<>(2); bufferPools.add(createBufferPoolMXBean(SharedSecrets.getJavaNioAccess() .getDirectBufferPool())); bufferPools.add(createBufferPoolMXBean(sun.nio.ch.FileChannelImpl .getMappedBufferPool())); } return bufferPools; } private static BufferPoolMXBean createBufferPoolMXBean(final JavaNioAccess.BufferPool pool) { return new BufferPoolMXBean() { private volatile ObjectName objname; // created lazily @Override public ObjectName getObjectName() { ObjectName result = objname; if (result == null) { synchronized (this) { result = objname; if (result == null) { result = Util.newObjectName(BUFFER_POOL_MXBEAN_NAME + “,name=” + pool.getName()); objname = result; } } } return result; } @Override public String getName() { return pool.getName(); } @Override public long getCount() { return pool.getCount(); } @Override public long getTotalCapacity() { return pool.getTotalCapacity(); } @Override public long getMemoryUsed() { return pool.getMemoryUsed(); } }; } //……}ManagementFactoryHelper的getBufferPoolMXBeans方法会通过createBufferPoolMXBean方法创建两个BufferPoolMXBean,然后添加到bufferPools其中一个是DirectBufferPool,一个是MappedBufferPool;他们分别使用SharedSecrets.getJavaNioAccess().getDirectBufferPool()以及sun.nio.ch.FileChannelImpl.getMappedBufferPool()来创建createBufferPoolMXBean方法使用匿名类创建了BufferPoolMXBean的实现;createBufferPoolMXBean方法接收JavaNioAccess.BufferPool参数,其getCount、getTotalCapacity、getMemoryUsed等均是直接使用pool的相关方法JavaNioAccess.BufferPooljava.base/jdk/internal/access/JavaNioAccess.javapublic interface JavaNioAccess { /* * Provides access to information on buffer usage. / interface BufferPool { String getName(); long getCount(); long getTotalCapacity(); long getMemoryUsed(); } BufferPool getDirectBufferPool();}JavaNioAccess里头定义了BufferPool接口,它定义了getName、getCount、getTotalCapacity、getMemoryUsed方法;除此之外JavaNioAccess还定义了getDirectBufferPool方法用于返回BufferPoolSharedSecretsjava.base/jdk/internal/access/SharedSecrets.javapublic class SharedSecrets { private static final Unsafe unsafe = Unsafe.getUnsafe(); private static JavaUtilJarAccess javaUtilJarAccess; private static JavaLangAccess javaLangAccess; private static JavaLangModuleAccess javaLangModuleAccess; private static JavaLangInvokeAccess javaLangInvokeAccess; private static JavaLangRefAccess javaLangRefAccess; private static JavaIOAccess javaIOAccess; private static JavaNetInetAddressAccess javaNetInetAddressAccess; private static JavaNetHttpCookieAccess javaNetHttpCookieAccess; private static JavaNetSocketAccess javaNetSocketAccess; private static JavaNetUriAccess javaNetUriAccess; private static JavaNetURLAccess javaNetURLAccess; private static JavaNetURLClassLoaderAccess javaNetURLClassLoaderAccess; private static JavaNioAccess javaNioAccess; private static JavaIOFileDescriptorAccess javaIOFileDescriptorAccess; private static JavaIOFilePermissionAccess javaIOFilePermissionAccess; private static JavaSecurityAccess javaSecurityAccess; private static JavaUtilZipFileAccess javaUtilZipFileAccess; private static JavaUtilResourceBundleAccess javaUtilResourceBundleAccess; private static JavaAWTAccess javaAWTAccess; private static JavaAWTFontAccess javaAWTFontAccess; private static JavaBeansAccess javaBeansAccess; private static JavaObjectInputStreamAccess javaObjectInputStreamAccess; private static JavaObjectInputFilterAccess javaObjectInputFilterAccess; private static JavaIORandomAccessFileAccess javaIORandomAccessFileAccess; private static JavaxCryptoSealedObjectAccess javaxCryptoSealedObjectAccess; //…… public static void setJavaNioAccess(JavaNioAccess jna) { javaNioAccess = jna; } public static JavaNioAccess getJavaNioAccess() { if (javaNioAccess == null) { // Ensure java.nio.Buffer is initialized, which provides the // shared secret. unsafe.ensureClassInitialized(java.nio.Buffer.class); } return javaNioAccess; } //……}SharedSecrets提供了JavaNioAccess的getter及setterBufferjava.base/java/nio/Buffer.javapublic abstract class Buffer { // Cached unsafe-access object static final Unsafe UNSAFE = Unsafe.getUnsafe(); /* * The characteristics of Spliterators that traverse and split elements * maintained in Buffers. / static final int SPLITERATOR_CHARACTERISTICS = Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED; // Invariants: mark <= position <= limit <= capacity private int mark = -1; private int position = 0; private int limit; private int capacity; // Used by heap byte buffers or direct buffers with Unsafe access // For heap byte buffers this field will be the address relative to the // array base address and offset into that array. The address might // not align on a word boundary for slices, nor align at a long word // (8 byte) boundary for byte[] allocations on 32-bit systems. // For direct buffers it is the start address of the memory region. The // address might not align on a word boundary for slices, nor when created // using JNI, see NewDirectByteBuffer(void, long). // Should ideally be declared final // NOTE: hoisted here for speed in JNI GetDirectBufferAddress long address; //…… static { // setup access to this package in SharedSecrets SharedSecrets.setJavaNioAccess( new JavaNioAccess() { @Override public JavaNioAccess.BufferPool getDirectBufferPool() { return Bits.BUFFER_POOL; } }); }}抽象类Buffer有个static代码块,里头创建了匿名JavaNioAccess,然后设置到了SharedSecrets中;其中匿名JavaNioAccess的getDirectBufferPool方法返回的是Bits.BUFFER_POOLFileChannelImpljava.base/sun/nio/ch/FileChannelImpl.javapublic class FileChannelImpl extends FileChannel{ // Memory allocation size for mapping buffers private static final long allocationGranularity; // Access to FileDescriptor internals private static final JavaIOFileDescriptorAccess fdAccess = SharedSecrets.getJavaIOFileDescriptorAccess(); // Used to make native read and write calls private final FileDispatcher nd; // File descriptor private final FileDescriptor fd; //…… // – Memory-mapped buffers – private static class Unmapper implements Runnable { // may be required to close file private static final NativeDispatcher nd = new FileDispatcherImpl(); // keep track of mapped buffer usage static volatile int count; static volatile long totalSize; static volatile long totalCapacity; private volatile long address; private final long size; private final int cap; private final FileDescriptor fd; private Unmapper(long address, long size, int cap, FileDescriptor fd) { assert (address != 0); this.address = address; this.size = size; this.cap = cap; this.fd = fd; synchronized (Unmapper.class) { count++; totalSize += size; totalCapacity += cap; } } public void run() { if (address == 0) return; unmap0(address, size); address = 0; // if this mapping has a valid file descriptor then we close it if (fd.valid()) { try { nd.close(fd); } catch (IOException ignore) { // nothing we can do } } synchronized (Unmapper.class) { count–; totalSize -= size; totalCapacity -= cap; } } } //…… /** * Invoked by sun.management.ManagementFactoryHelper to create the management * interface for mapped buffers. */ public static JavaNioAccess.BufferPool getMappedBufferPool() { return new JavaNioAccess.BufferPool() { @Override public String getName() { return “mapped”; } @Override public long getCount() { return Unmapper.count; } @Override public long getTotalCapacity() { return Unmapper.totalCapacity; } @Override public long getMemoryUsed() { return Unmapper.totalSize; } }; } //……}FileChannelImpl定义了getMappedBufferPool方法,返回的是匿名JavaNioAccess.BufferPool,其相关返回实现直接使用Unmapper的对应方法;Unmapper实现了Runnable接口小结BufferPoolMXBean接口继承了PlatformManagedObject,它定义了getName、getCount、getTotalCapacity、getMemoryUsed方法ManagementFactoryHelper的getBufferPoolMXBeans方法会通过createBufferPoolMXBean方法创建两个BufferPoolMXBean,然后添加到bufferPools;其中一个是DirectBufferPool,一个是MappedBufferPool;他们分别使用SharedSecrets.getJavaNioAccess().getDirectBufferPool()以及sun.nio.ch.FileChannelImpl.getMappedBufferPool()来创建createBufferPoolMXBean方法接收JavaNioAccess.BufferPool参数;抽象类Buffer有个static代码块,里头创建了匿名JavaNioAccess,然后设置到了SharedSecrets中;其中匿名JavaNioAccess的getDirectBufferPool方法返回的是Bits.BUFFER_POOL;FileChannelImpl定义了getMappedBufferPool方法,返回的是匿名JavaNioAccess.BufferPool,其相关返回实现直接使用Unmapper的对应方法;Unmapper实现了Runnable接口docInterface BufferPoolMXBean ...

March 30, 2019 · 6 min · jiezi

聊聊openjdk的jhsdb工具

序本文主要研究一下openjdk的jhsdb工具sa-jdi.jarexport JAVA_HOME="/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home"chmod +x $JAVA_HOME/lib/sa-jdi.jarjava -cp $JAVA_HOME/lib/sa-jdi.jar sun.jvm.hotspot.HSDBjava -cp $JAVA_HOME/lib/sa-jdi.jar sun.jvm.hotspot.CLHSDB在java9之前,JAVA_HOME/lib目录下有个sa-jdi.jar,可以通过如上命令启动HSDB(图形界面)及CLHSDB(命令行)sa-jdi.jar中的sa的全称为Serviceability Agent,它之前是sun公司提供的一个用于协助调试HotSpot的组件,而HSDB便是使用Serviceability Agent来实现的HSDB就是HotSpot Debugger的简称,由于Serviceability Agent在使用的时候会先attach进程,然后暂停进程进行snapshot,最后deattach进程(进程恢复运行),所以在使用HSDB时要注意jhsdb/ # jhsdb clhsdb command line debugger debugd debug server hsdb ui debugger jstack –help to get more information jmap –help to get more information jinfo –help to get more information jsnap –help to get more informationjhsdb是java9引入的,可以在JAVA_HOME/bin目录下找到jhsdb;它取代了jdk9之前的JAVA_HOME/lib/sa-jdi.jarjhsdb有clhsdb、debugd、hsdb、jstack、jmap、jinfo、jsnap这些mode可以使用其中hsdb为ui debugger,就是jdk9之前的sun.jvm.hotspot.HSDB;而clhsdb即为jdk9之前的sun.jvm.hotspot.CLHSDBjhsdb jstack/ # jhsdb jstack –help –locks to print java.util.concurrent locks –mixed to print both java and native frames (mixed mode) –exe executable image name –core path to coredump –pid pid of process to attach–pid用于指定JVM的进程ID;–exe用于指定可执行文件;–core用于指定core dump文件异常jhsdb jstack –mixed –pid 1//……Caused by: sun.jvm.hotspot.debugger.DebuggerException: get_thread_regs failed for a lwp at jdk.hotspot.agent/sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal.getThreadIntegerRegisterSet0(Native Method) at jdk.hotspot.agent/sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal$1GetThreadIntegerRegisterSetTask.doit(LinuxDebuggerLocal.java:534) at jdk.hotspot.agent/sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal$LinuxDebuggerLocalWorkerThread.run(LinuxDebuggerLocal.java:151)如果出现这个异常表示是采用jdk版本的问题,可以尝试一下其他jdk编译版本debugger/ # jhsdb jstack –locks –pid 1Attaching to process ID 1, please wait…Debugger attached successfully.Server compiler detected.JVM version is 12+33Deadlock Detection:No deadlocks found.“DestroyJavaVM” #32 prio=5 tid=0x000055c3b5be0800 nid=0x6 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE JavaThread state: _thread_blockedLocked ownable synchronizers: - None"http-nio-8080-Acceptor-0" #30 daemon prio=5 tid=0x000055c3b5d71800 nid=0x2f runnable [0x00007fa0d13de000] java.lang.Thread.State: RUNNABLE JavaThread state: _thread_in_native - sun.nio.ch.ServerSocketChannelImpl.accept0(java.io.FileDescriptor, java.io.FileDescriptor, java.net.InetSocketAddress[]) @bci=0 (Interpreted frame) - sun.nio.ch.ServerSocketChannelImpl.accept(java.io.FileDescriptor, java.io.FileDescriptor, java.net.InetSocketAddress[]) @bci=4, line=525 (Interpreted frame) - sun.nio.ch.ServerSocketChannelImpl.accept() @bci=41, line=277 (Interpreted frame) - org.apache.tomcat.util.net.NioEndpoint.serverSocketAccept() @bci=4, line=448 (Interpreted frame) - org.apache.tomcat.util.net.NioEndpoint.serverSocketAccept() @bci=1, line=70 (Interpreted frame) - org.apache.tomcat.util.net.Acceptor.run() @bci=98, line=95 (Interpreted frame) - java.lang.Thread.run() @bci=11, line=835 (Interpreted frame)Locked ownable synchronizers: - <0x00000000e3aab6e0>, (a java/util/concurrent/locks/ReentrantLock$NonfairSync)“http-nio-8080-ClientPoller-0” #29 daemon prio=5 tid=0x000055c3b5c20000 nid=0x2e runnable [0x00007fa0d14df000] java.lang.Thread.State: RUNNABLE JavaThread state: _thread_in_native - sun.nio.ch.EPoll.wait(int, long, int, int) @bci=0 (Interpreted frame) - sun.nio.ch.EPollSelectorImpl.doSelect(java.util.function.Consumer, long) @bci=96, line=120 (Interpreted frame) - sun.nio.ch.SelectorImpl.lockAndDoSelect(java.util.function.Consumer, long) @bci=42, line=124 (Interpreted frame) - locked <0x00000000e392ece8> (a sun.nio.ch.EPollSelectorImpl) - locked <0x00000000e392ee38> (a sun.nio.ch.Util$2) - sun.nio.ch.SelectorImpl.select(long) @bci=31, line=136 (Interpreted frame) - org.apache.tomcat.util.net.NioEndpoint$Poller.run() @bci=55, line=743 (Interpreted frame) - java.lang.Thread.run() @bci=11, line=835 (Interpreted frame)Locked ownable synchronizers: - None"http-nio-8080-exec-10" #28 daemon prio=5 tid=0x000055c3b48d6000 nid=0x2d waiting on condition [0x00007fa0d15e0000] java.lang.Thread.State: WAITING (parking) JavaThread state: _thread_blocked - jdk.internal.misc.Unsafe.park(boolean, long) @bci=0 (Interpreted frame) - parking to wait for <0x00000000e3901670> (a java/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject) - java.util.concurrent.locks.LockSupport.park(java.lang.Object) @bci=14, line=194 (Interpreted frame) - java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await() @bci=42, line=2081 (Interpreted frame) - java.util.concurrent.LinkedBlockingQueue.take() @bci=27, line=433 (Interpreted frame) - org.apache.tomcat.util.threads.TaskQueue.take() @bci=36, line=107 (Interpreted frame) - org.apache.tomcat.util.threads.TaskQueue.take() @bci=1, line=33 (Interpreted frame) - java.util.concurrent.ThreadPoolExecutor.getTask() @bci=147, line=1054 (Interpreted frame) - java.util.concurrent.ThreadPoolExecutor.runWorker(java.util.concurrent.ThreadPoolExecutor$Worker) @bci=26, line=1114 (Interpreted frame) - java.util.concurrent.ThreadPoolExecutor$Worker.run() @bci=5, line=628 (Interpreted frame) - org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run() @bci=4, line=61 (Interpreted frame) - java.lang.Thread.run() @bci=11, line=835 (Interpreted frame) //……/ # jhsdb jstack –mixed –pid 1Attaching to process ID 1, please wait…Debugger attached successfully.Server compiler detected.JVM version is 12+33Deadlock Detection:No deadlocks found.—————– 47 —————–“http-nio-8080-Acceptor-0” #30 daemon prio=5 tid=0x000055c3b5d71800 nid=0x2f runnable [0x00007fa0d13de000] java.lang.Thread.State: RUNNABLE JavaThread state: _thread_in_native0x00007fa0ee0923ad ????????—————– 46 —————–“http-nio-8080-ClientPoller-0” #29 daemon prio=5 tid=0x000055c3b5c20000 nid=0x2e runnable [0x00007fa0d14df000] java.lang.Thread.State: RUNNABLE JavaThread state: _thread_in_native0x00007fa0ee05f3d0 epoll_pwait + 0x1d0x00007fa0daa97810 * sun.nio.ch.EPoll.wait(int, long, int, int) bci:0 (Interpreted frame)0x00007fa0daa91680 * sun.nio.ch.EPollSelectorImpl.doSelect(java.util.function.Consumer, long) bci:96 line:120 (Interpreted frame)0x00007fa0db85f57c * sun.nio.ch.SelectorImpl.lockAndDoSelect(java.util.function.Consumer, long) bci:42 line:124 (Compiled frame)* sun.nio.ch.SelectorImpl.select(long) bci:31 line:136 (Compiled frame)* org.apache.tomcat.util.net.NioEndpoint$Poller.run() bci:55 line:743 (Interpreted frame)0x00007fa0daa91c88 * java.lang.Thread.run() bci:11 line:835 (Interpreted frame)0x00007fa0daa88849 <StubRoutines>0x00007fa0ed122952 _ZN9JavaCalls11call_helperEP9JavaValueRK12methodHandleP17JavaCallArgumentsP6Thread + 0x3c20x00007fa0ed1208d0 _ZN9JavaCalls12call_virtualEP9JavaValue6HandleP5KlassP6SymbolS6_P6Thread + 0x2000x00007fa0ed1ccfc5 _ZL12thread_entryP10JavaThreadP6Thread + 0x750x00007fa0ed74f3a3 _ZN10JavaThread17thread_main_innerEv + 0x1030x00007fa0ed74c3f5 _ZN6Thread8call_runEv + 0x750x00007fa0ed4a477e _ZL19thread_native_entryP6Thread + 0xee//……–locks或者–mixed花费的时间可能比较长(几分钟,可能要将近6分钟),因而进程暂停的时间也可能比较长,在使用这两个选项时要注意jhsdb jmapjmap -heap pid/ # jmap -heap 1Error: -heap option usedCannot connect to core dump or remote debug server. Use jhsdb jmap insteadjdk9及以上版本使用jmap -heap pid命令查看当前heap使用情况时,发现报错,提示需要使用jhsdb jmap来替代jhsdb jmap pid/ # jhsdb jmap 1sh: jhsdb: not found发现jlink的时候没有添加jdk.hotspot.agent这个module,添加了这个module之后可以发现JAVA_HOME/bin目录下就有了jhsdbPTRACE_ATTACH failed/ # jhsdb jmap 1You have to set –pid or –exe. <no option> to print same info as Solaris pmap –heap to print java heap summary –binaryheap to dump java heap in hprof binary format –dumpfile name of the dump file –histo to print histogram of java object heap –clstats to print class loader statistics –finalizerinfo to print information on objects awaiting finalization –exe executable image name –core path to coredump –pid pid of process to attach/ # jhsdb jmap –heap –pid 1Attaching to process ID 1, please wait…ERROR: ptrace(PTRACE_ATTACH, ..) failed for 1: Operation not permittedError attaching to process: sun.jvm.hotspot.debugger.DebuggerException: Can’t attach to the process: ptrace(PTRACE_ATTACH, ..) failed for 1: Operation not permittedsun.jvm.hotspot.debugger.DebuggerException: sun.jvm.hotspot.debugger.DebuggerException: Can’t attach to the process: ptrace(PTRACE_ATTACH, ..) failed for 1: Operation not permitted at jdk.hotspot.agent/sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal$LinuxDebuggerLocalWorkerThread.execute(LinuxDebuggerLocal.java:176) at jdk.hotspot.agent/sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal.attach(LinuxDebuggerLocal.java:336) at jdk.hotspot.agent/sun.jvm.hotspot.HotSpotAgent.attachDebugger(HotSpotAgent.java:672) at jdk.hotspot.agent/sun.jvm.hotspot.HotSpotAgent.setupDebuggerLinux(HotSpotAgent.java:612) at jdk.hotspot.agent/sun.jvm.hotspot.HotSpotAgent.setupDebugger(HotSpotAgent.java:338) at jdk.hotspot.agent/sun.jvm.hotspot.HotSpotAgent.go(HotSpotAgent.java:305) at jdk.hotspot.agent/sun.jvm.hotspot.HotSpotAgent.attach(HotSpotAgent.java:141) at jdk.hotspot.agent/sun.jvm.hotspot.tools.Tool.start(Tool.java:185) at jdk.hotspot.agent/sun.jvm.hotspot.tools.Tool.execute(Tool.java:118) at jdk.hotspot.agent/sun.jvm.hotspot.tools.JMap.main(JMap.java:176) at jdk.hotspot.agent/sun.jvm.hotspot.SALauncher.runJMAP(SALauncher.java:326) at jdk.hotspot.agent/sun.jvm.hotspot.SALauncher.main(SALauncher.java:455)Caused by: sun.jvm.hotspot.debugger.DebuggerException: Can’t attach to the process: ptrace(PTRACE_ATTACH, ..) failed for 1: Operation not permitted at jdk.hotspot.agent/sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal.attach0(Native Method) at jdk.hotspot.agent/sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal$1AttachTask.doit(LinuxDebuggerLocal.java:326) at jdk.hotspot.agent/sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal$LinuxDebuggerLocalWorkerThread.run(LinuxDebuggerLocal.java:151)发现PTRACE_ATTACH被docker禁用了,需要在运行容器时启用PTRACE_ATTACHdocker启用SYS_PTRACEdocker run –cap-add=SYS_PTRACE之后就可以正常使用jhsdb如下:/ # jhsdb jmap –heap –pid 1Attaching to process ID 1, please wait…Debugger attached successfully.Server compiler detected.JVM version is 12+33using thread-local object allocation.Shenandoah GC with 4 thread(s)Heap Configuration: MinHeapFreeRatio = 40 MaxHeapFreeRatio = 70 MaxHeapSize = 523763712 (499.5MB) NewSize = 1363144 (1.2999954223632812MB) MaxNewSize = 17592186044415 MB OldSize = 5452592 (5.1999969482421875MB) NewRatio = 2 SurvivorRatio = 8 MetaspaceSize = 21807104 (20.796875MB) CompressedClassSpaceSize = 1073741824 (1024.0MB) MaxMetaspaceSize = 17592186044415 MB ShenandoahRegionSize = 262144 (0.25MB)Heap Usage:Shenandoah Heap: regions = 1997 capacity = 523501568 (499.25MB) used = 70470552 (67.2059555053711MB) committed = 144441344 (137.75MB)jhsdb jinfo/ # jhsdb jinfo –help –flags to print VM flags –sysprops to print Java System properties <no option> to print both of the above –exe executable image name –core path to coredump –pid pid of process to attach使用jhsdb显示jinfo的sysprops如下:/ # jhsdb jinfo –sysprops –pid 1Attaching to process ID 1, please wait…Debugger attached successfully.Server compiler detected.JVM version is 12+33awt.toolkit = sun.awt.X11.XToolkitjava.specification.version = 12sun.jnu.encoding = UTF-8//……这个命令其实跟jinfo -sysprops 1是等价的jhsdb jsnap/ # jhsdb jsnap –pid 1Attaching to process ID 1, please wait…Debugger attached successfully.Server compiler detected.JVM version is 12+33java.threads.started=27 event(s)java.threads.live=24java.threads.livePeak=24java.threads.daemon=20java.cls.loadedClasses=8250 event(s)java.cls.unloadedClasses=1 event(s)java.cls.sharedLoadedClasses=0 event(s)java.cls.sharedUnloadedClasses=0 event(s)java.ci.totalTime=18236958158 tick(s)java.property.java.vm.specification.version=12java.property.java.vm.specification.name=Java Virtual Machine Specificationjava.property.java.vm.specification.vendor=Oracle Corporationjava.property.java.vm.version=12+33java.property.java.vm.name=OpenJDK 64-Bit Server VMjava.property.java.vm.vendor=Azul Systems, Inc.java.property.java.vm.info=mixed modejava.property.jdk.debug=release//……jhsdb jsnap的功能主要是由jdk.hotspot.agent模块中的sun.jvm.hotspot.tools.JSnap.java来提供的,它可以用于查看threads及class loading/unloading相关的event、JVM属性参数等,其中–all可以显示更多的JVM属性参数jhsdb与jcmdjhsdb: A New Tool for JDK 9这篇文章中列出了jhsdb与jcmd的等价命令,如下图:小结在java9之前,JAVA_HOME/lib目录下有个sa-jdi.jar,可以通过如上命令启动HSDB(图形界面)及CLHSDB(命令行);sa-jdi.jar中的sa的全称为Serviceability Agent,它之前是sun公司提供的一个用于协助调试HotSpot的组件,而HSDB便是使用Serviceability Agent来实现的;HSDB就是HotSpot Debugger的简称,由于Serviceability Agent在使用的时候会先attach进程,然后暂停进程进行snapshot,最后deattach进程(进程恢复运行),所以在使用HSDB时要注意jhsdb是java9引入的,可以在JAVA_HOME/bin目录下找到jhsdb;它取代了jdk9之前的JAVA_HOME/lib/sa-jdi.jar;jhsdb有clhsdb、debugd、hsdb、jstack、jmap、jinfo、jsnap这些mode可以使用;其中hsdb为ui debugger,就是jdk9之前的sun.jvm.hotspot.HSDB;而clhsdb即为jdk9之前的sun.jvm.hotspot.CLHSDBjhsdb在jdk.hotspot.agent这个模块中;对于jhsdb jstack的–locks或者–mixed命令花费的时间可能比较长(几分钟,可能要将近6分钟),因而进程暂停的时间也可能比较长,在使用这两个选项时要注意;对于jdk9及以后的版本不再使用jmap -heap命令来查询heap内存情况,需要用jhsdb jmap –heap –pid来替代;使用jhsdb jmap需要在运行容器时启用PTRACE_ATTACH才可以docJVM信息查看jhsdbjdk.hotspot.agent jhsdbjhsdb: A New Tool for JDK 9jcmd: One JDK Command-Line Tool to Rule Them AllJVM in Docker and PTRACE_ATTACHServiceability in HotSpotThe HotSpot™ Serviceability Agent: An out-of-process high level debugger for a Java™ virtual machine ...

March 27, 2019 · 5 min · jiezi

聊聊openjdk的jvm.cfg文件

序本文主要研究一下openjdk的jvm.cfg文件jdk8/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/jvm.cfg# List of JVMs that can be used as an option to java, javac, etc.# Order is important – first in this list is the default JVM.# NOTE that this both this file and its format are UNSUPPORTED and# WILL GO AWAY in a future release.## You may also select a JVM in an arbitrary location with the# “-XXaltjvm=<jvm_dir>” option, but that too is unsupported# and may not be available in a future release.#-server KNOWN-client IGNORE对于jdk8该文件在JAVA_HOME/jre/lib/目录下;其注释显示该配置文件用于配置java、javac能够使用的option,其中配置顺序非常重要,第一个为default JVM(不管其是KNOWN还是IGNORE;IGNORE仅仅是禁用VM option;ERROR则报错显示not supported);可以看到这里-server是默认的,而-client则被忽略jdk9-12/Library/Java/JavaVirtualMachines/jdk-12.jdk/Contents/Home/lib/jvm.cfg-server KNOWN-client IGNORE对于jdk9、10、11、12该文件在JAVA_HOME/lib/目录下设置-client为default对于jdk12,把-client移到前面-client IGNORE-server KNOWN执行java -version显示如下java -versionError: missing client' JVM at /Library/Java/JavaVirtualMachines/jdk-12.jdk/Contents/Home/lib/client/libjvm.dylib’.Please install or use the JRE or JDK that contains these missing components.可以看到对于mac的jdk12,把client设置为default则报错禁用client-server KNOWN-client ERROR执行java -client -version显示如下java -client -versionError: client VM not supported可以看到设置-client为ERROR,则报错显示not supported删除jvm.cfgjava -versionError: could not open `/Library/Java/JavaVirtualMachines/jdk-12.jdk/Contents/Home/lib/jvm.cfg’可以看到删除jvm.cfg,执行java -version则会报错小结jvm.cfg文件用于配置java、javac能够使用的option,其中配置顺序非常重要,第一个为default JVM(不管其是KNOWN还是IGNORE;IGNORE仅仅是禁用VM option;ERROR则报错显示not supported)对于jdk8该文件在JAVA_HOME/jre/lib/目录下;对于jdk9、10、11、12该文件在JAVA_HOME/lib/目录下;删除jvm.cfg文件的话,则执行java命令会报错可以看到对于mac来说其open jdk的jvm.cfg中-server位于-client前面,-server是default JVM,而-client则被忽略docThe Java HotSpot VM Architecture OverviewWhat is the purpose of jvm.cfg file in relation to Java?Running the JVM in server modeServer-Class Machine DetectionChange Default Java VM to ClientOpenJDK default options to always use the server VM ...

March 26, 2019 · 1 min · jiezi

聊聊HotSpot VM的Native Memory Tracking

序本文主要研究一下HotSpot VM的Native Memory TrackingNative Memory Trackingjava8给HotSpot VM引入了Native Memory Tracking (NMT)特性,可以用于追踪JVM的内部内存使用使用开启-XX:NativeMemoryTracking=summary使用-XX:NativeMemoryTracking=summary可以用于开启NMT,其中该值默认为off,可以设置summary、detail来开启;开启的话,大概会增加5%-10%的性能消耗查看/ # jcmd 1 VM.native_memory summary/ # jcmd 1 VM.native_memory summary scale=MB使用jcmd pid VM.native_memory可以查看,后面可以加summary或者detail,如果是开启summary的,就只能使用summary;其中scale参数可以指定展示的单位,可以为KB或者MB或者GB创建baseline/ # jcmd 1 VM.native_memory baseline1:Baseline succeeded创建baseline之后可以用summary.diff来对比查看diff/ # jcmd 1 VM.native_memory summary.diff使用summary.diff来查看跟baseline对比的统计信息shutdown时输出-XX:+UnlockDiagnosticVMOptions -XX:+PrintNMTStatistics使用上述命令可以在jvm shutdown的时候输出整体的native memory统计关闭/ # jcmd 1 VM.native_memory shutdown1:Native memory tracking has been turned off使用jcmd pid VM.native_memory shutdown可以用于关闭NMT;注意使用jcmd关闭之后貌似没有对应jcmd命令来开启实例/ # jcmd 1 VM.native_memory summary scale=MB1:Native Memory Tracking:Total: reserved=2175MB, committed=682MB- Java Heap (reserved=501MB, committed=463MB) (mmap: reserved=501MB, committed=463MB)- Class (reserved=1070MB, committed=50MB) (classes #8801) ( instance classes #8204, array classes #597) (malloc=2MB #24660) (mmap: reserved=1068MB, committed=49MB) ( Metadata: ) ( reserved=44MB, committed=43MB) ( used=42MB) ( free=1MB) ( waste=0MB =0.00%) ( Class space:) ( reserved=1024MB, committed=6MB) ( used=5MB) ( free=0MB) ( waste=0MB =0.00%)- Thread (reserved=228MB, committed=27MB) (thread #226) (stack: reserved=227MB, committed=26MB) (malloc=1MB #1139)- Code (reserved=243MB, committed=17MB) (malloc=1MB #5509) (mmap: reserved=242MB, committed=16MB)- GC (reserved=23MB, committed=15MB) (malloc=8MB #11446) (mmap: reserved=16MB, committed=7MB)- Compiler (reserved=26MB, committed=26MB) (malloc=2MB #1951) (arena=24MB #13)- Internal (reserved=5MB, committed=5MB) (malloc=3MB #9745) (mmap: reserved=2MB, committed=2MB)- Other (reserved=2MB, committed=2MB) (malloc=2MB #202)- Symbol (reserved=10MB, committed=10MB) (malloc=8MB #233939) (arena=3MB #1)- Native Memory Tracking (reserved=5MB, committed=5MB) (tracking overhead=5MB)- Arena Chunk (reserved=63MB, committed=63MB) (malloc=63MB)可以看到整个memory主要包含了Java Heap、Class、Thread、Code、GC、Compiler、Internal、Other、Symbol、Native Memory Tracking、Arena Chunk这几部分;其中reserved表示应用可用的内存大小,committed表示应用正在使用的内存大小Java Heap部分表示heap内存目前占用了463MB;Class部分表示已经加载的classes个数为8801,其metadata占用了50MB;Thread部分表示目前有225个线程,占用了27MB;Code部分表示JIT生成的或者缓存的instructions占用了17MB;GC部分表示目前已经占用了15MB的内存空间用于帮助GC;Code部分表示compiler生成code的时候占用了26MB;Internal部分表示命令行解析、JVMTI等占用了5MB;Other部分表示尚未归类的占用了2MB;Symbol部分表示诸如string table及constant pool等symbol占用了10MB;Native Memory Tracking部分表示该功能自身占用了5MB;Arena Chunk部分表示arena chunk占用了63MB一个arena表示使用malloc分配的一个memory chunk,这些chunks可以被其他subsystems做为临时内存使用,比如pre-thread的内存分配,它的内存释放是成bulk的小结java8给HotSpot VM引入了Native Memory Tracking (NMT)特性,可以用于追踪JVM的内部内存使用使用-XX:NativeMemoryTracking=summary可以用于开启NMT,其中该值默认为off,可以设置summary、detail来开启;开启的话,大概会增加5%-10%的性能消耗;使用-XX:+UnlockDiagnosticVMOptions -XX:+PrintNMTStatistics可以在jvm shutdown的时候输出整体的native memory统计;其他的可以使用jcmd pid VM.native_memory相关命令进行查看、diff、shutdown等整个memory主要包含了Java Heap、Class、Thread、Code、GC、Compiler、Internal、Other、Symbol、Native Memory Tracking、Arena Chunk这几部分;其中reserved表示应用可用的内存大小,committed表示应用正在使用的内存大小docNative Memory TrackingNative Memory Tracking diagnostic-toolsNMT Memory CategoriesMemory footprint of the JVMNative Memory Tracking in JVM ...

March 25, 2019 · 2 min · jiezi

JDK 12又来了,我学不动了...

写在前面看到 JDK 12又发布了,萌新不知不觉感觉瑟瑟发抖,从 Java 1.8的函数式编程思维和范式 到 Java 1.9的模块化特性的加持 以及还没来得及深切感受一下 Java 1.11 的 ZGC强大之后,这次JDK 12到底有搞了些啥事情呢?我真的学不动了,我该怎么办呢?不管怎样,下面还是来看一下JDK 12的新特性解(fan)读(yi)吧!低暂停延时的垃圾收集器 (实验版)A Low-Pause-Time Garbage Collector (Experimental)添加一个名为 Shenandoah的新垃圾收集 (GC)算法,该算法通过与正在运行的 Java线程并发执行回收工作来减少 GC暂停时间。Shenandoah的暂停时间与堆大小无关,这意味着无论堆大小是 200MB 还是 200GB,都将拥有相同的暂停时间。微基准测试套件Microbenchmark Suite在 JDK源代码中添加了一组基本的微基准测试套件,使得开发人员无论运行现有的微基准测试或者创建新的微基准测试都变得十分便利。Switch 表达式 (预览版)Switch Expressions (Preview)这是一个预览版语言特性。通过对 switch语法进行了扩展,使其不仅可以作为语句(statement),还可以作为表达式(expression),并且两种形式都可以使用“传统的”或“简化的”语法用于作用于不同的范围或者控制执行流。这些更改将会简化日常编码,并且为在 switch中使用模式匹配 (JEP 305) 做好了准备。JVM 常量APIJVM Constants API引入一个API来建模关键类文件(key class-file)和运行时构件(run-time artifacts)的标称描述,特别是对那些可从常量池加载的常量。仅保留 AArch64 实现One AArch64 Port, Not Two删除与 arm64实现相关的所有源代码,同时保留 32-bit ARM和 64-bit aarch64实现。删除这些实现是为了让所有代码贡献者集中精力于一个实现上,从而消除维护两个实现所需付出的重复工作。默认类数据共享归档文件Default CDS Archives增强 JDK构建过程,在 64位平台上使用默认的类列表生成类数据共享(class data-sharing,CDS)存档。可中断的 G1 Mixed GCAbortable Mixed Collections for G1如果 Mixed GC 的 G1 存在超出暂停目标的可能性,则使其可被中止。G1未使用分配内存即时返回Promptly Return Unused Committed Memory from G1增强 G1垃圾收集器,以便在空闲时自动将 Java 堆内存返回给操作系统。参考文献http://openjdk.java.net/jeps/189http://openjdk.java.net/jeps/230http://openjdk.java.net/jeps/325http://openjdk.java.net/jeps/334http://openjdk.java.net/jeps/340http://openjdk.java.net/jeps/341http://openjdk.java.net/jeps/344http://openjdk.java.net/jeps/346后 记啥都不说了,JDK 13您慢点出吧,快要掉队了,我跟不上了…由于能力有限,若有错误或者不当之处,还请大家批评指正,一起学习交流!My Personal Blog:CodeSheep 程序羊 ...

March 20, 2019 · 1 min · jiezi

您收到一封 2019 阿里云峰会 (北京) 邀请函

摘要: 阿里云峰会(北京)开发者专场以“云原生和可见的云未来”为主题,不仅涵盖 2 场重大发布,更设置人工智能、机器学习、实时计算、云原生实践等国内外最热门的话题。我们希望和开发者一起见证云原生如此热烈的当下,云未来的各种可能性,希望您的加入!2019 年是阿里云成立的第 10 年,在过去的 10 年间,阿里云引领了国内云基础设施市场;在当下,我们希望可以和您一起分享阿里云的新战略和新思考。2019 年将是云原生在中国爆发和落地的一年,在这样的背景下,阿里将如何探索实时计算新架构?数据库的研发流程将如何演进?我们在代码智能化上又有怎样的思考和实践?云原生又将如何赋能AI、基因等各行业?【开发者专场三大亮点】亮点一阿里巴巴集团副总裁/达摩院首席数据科学家/数据库产品事业部负责人 李飞飞联合 阿里云云智能战略与合作部总经理 刘湘雯 共同畅谈开发者与可见的云未来。亮点二阿里云智能基础产品事业部研究员 周经森 发布 OpenJDK 长期支持版本 Alibaba Dragonwell亮点三重磅发布:CNCF X Alibaba 云原生技术课程免费报名报名地址:https://www.yunqi.org/goPage?page=bj_signup_mb&activeId=2&ticketTypeId=39&channelId=23【开发者专场议题】本文作者:amber涂南阅读原文本文为云栖社区原创内容,未经允许不得转载。

March 7, 2019 · 1 min · jiezi

深入理解 lambda表达式 与 MethodReference(四)

package com.java.design.java8.MethodReference;import com.java.design.java8.entity.Student;import org.junit.Before;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.test.context.junit4.SpringRunner;import java.util.Arrays;import java.util.List;import java.util.function.Supplier;/** * @author 陈杨 */@RunWith(SpringRunner.class)@SpringBootTestpublic class MethodReference {一、测试数据准备private List<Student> students;private List<String> snames;private Student studentSupplier(Supplier<Student> studentSupplier) { return studentSupplier.get();}// private StudentConstructor studentConstructor =// (id, name, sex, age, addr, salary) ->// new Student(id, name, sex, age, addr, salary);private StudentConstructor studentConstructor = Student::new;private Student studentAllArgs(Integer id, String name, String sex, Integer age, String addr, Double salary) { return studentConstructor.studentAllArgs(id, name, sex, age, addr, salary);}@Beforepublic void init() { Student kirito = new Student(1, “Kirito”, “Male”, 18, “Sword Art Online”, 999999999.0); Student Asuna = new Student(2, “Asuna”, “Female”, 17, “Sword Art Online”, 999999999.0); Student Sinon = new Student(3, “Sinon”, “Female”, 16, “Gun Gale Online”, 999999999.0); Student Yuuki = new Student(4, “Yuuki”, “Female”, 15, “Alfheim Online”, 999999999.0); Student Alice = new Student(5, “Alice”, “Female”, 14, “Alicization”, 999999999.0); students = Arrays.asList(kirito, Asuna, Sinon, Yuuki, Alice); snames = Arrays.asList(“kirito”, “Asuna”, “Sinon”, “Yuuki”, “Alice”);}二、方法引用 引入@Testpublic void testMethodReference() { // MethodReference 方法引用 List<String> Iloveyou = Arrays.asList(“Kirito”, “Love”, “Asuna”); //集合遍历 Lambda System.out.println("—————————————\n"); System.out.println(“集合遍历 Lambda”); Iloveyou.forEach(str -> System.out.println(str)); //集合遍历 MethodReference System.out.println("—————————————\n"); System.out.println(“集合遍历 MethodReference”); Iloveyou.forEach(System.out::println);三、什么是方法引用// MethodReference// 方法引用是Lambda表达式的特殊替换// 方法引用本质是一个 函数指针 Function Pointer// 这个指针指向被引用方法// eg: 方法引用System.out::println 指向System.out.println()这个函数四、方法引用的分类1、 静态方法引用// 1、 静态方法引用// 静态方法引用 类名::静态方法名// 静态方法引用 功能实现等价于 调用 类的静态方法// 静态方法引用 与 调用 无任何关系// 类名.静态方法名 –>方法调用 显示传参// 类名::静态方法名 –>方法引用 隐式传参 编译器自动推断 方法引用的表达式 函数指针 指向 被引用函数System.out.println("—————————————\n");System.out.println(" 静态方法引用 按年龄排序");students.sort(StaticStudentComparator::staticCompareStudentByAge);students.forEach(System.out::println);System.out.println("—————————————\n");System.out.println(" 静态方法引用 按姓名排序");students.sort(StaticStudentComparator::staticCompareStudentByName);students.forEach(System.out::println);2、 对象实例方法引用// 2、 对象实例方法引用// 对象实例方法引用 引用名(对象名)::实例方法名// 对象实例方法引用 功能实现等价于 调用 对象实例 所拥有的 实例方法StudentComparator studentComparator = new StudentComparator();System.out.println("—————————————\n");System.out.println(" 静态方法引用 按年龄排序");students.sort(studentComparator::compareStudentByAge);students.forEach(System.out::println);System.out.println("—————————————\n");System.out.println(" 对象实例方法引用 按姓名排序");students.sort(studentComparator::compareStudentByName);students.forEach(System.out::println);3、 类实例方法引用// 3、 类实例方法引用// 类实例方法引用 类名::实例方法名System.out.println("—————————————\n");System.out.println(" 类实例方法引用 按年龄排序");students.sort(Student::classCompareStudentByAge);students.forEach(System.out::println);System.out.println("—————————————\n");System.out.println(" 类实例方法引用 按姓名排序");students.sort(Student::classCompareStudentByName);students.forEach(System.out::println);System.out.println("—————————————\n");System.out.println(" 类实例方法引用 容易理解的 字符串排序");snames.sort(String::compareToIgnoreCase);snames.forEach(System.out::println);4、 构造方法引用// 4、 构造方法引用// 构造方法引用 类名::new// 注意: 实体类Student 事先 有定义好的 全参构造方法 与无参构造方法// 若没有构造方法 需要自行添加 否则报错// Student::new 可以根据参数不同 对构造方法进行自动识别 重载// 利用无参构造方法构造studentNoArgs对象System.out.println("—————————————\n");System.out.println(“利用无参构造方法构造studentNoArgs对象”);Student studentNoArgs = this.studentSupplier(Student::new);System.out.println(studentNoArgs);// 利用自定义全参构造方法构造student对象System.out.println("—————————————\n");System.out.println(“利用全参构造方法构造studentNoArgs对象”);Student Silica = this.studentAllArgs (6, “Silica”, “Female”, 10, “Sword Art Online”, 999999999.0);System.out.println(Silica); }}五、StaticStudentComparator类 (静态方法实例引用)import com.java.design.java8.entity.Student;import java.util.Comparator;public class StaticStudentComparator { static Comparator<Student> studentAgeComparator = (first, last) -> first.getAge() - last.getAge(); static Comparator<Student> studentNameComparator = (first, last) -> first.getName().compareToIgnoreCase(last.getName()); public static int staticCompareStudentByAge(Student first, Student last) { return studentAgeComparator.compare(first, last); } public static int staticCompareStudentByName(Student first, Student last) { return studentNameComparator.compare(first, last); }}六、StudentComparator类 (对象方法实例引用)import com.java.design.java8.entity.Student;import java.util.Comparator;public class StudentComparator { Comparator<Student> studentAgeComparator = (first, last) -> first.getAge() - last.getAge(); Comparator<Student> studentNameComparator = (first, last) -> first.getName().compareToIgnoreCase(last.getName()); public int compareStudentByAge(Student first, Student last) { return studentAgeComparator.compare(first, last); } public int compareStudentByName(Student first, Student last) { return studentNameComparator.compare(first, last); }}七、StudentConstructor @FunctionalInterface接口 (构造方法实例引用)import com.java.design.java8.entity.Student;@FunctionalInterfacepublic interface StudentConstructor { Student studentAllArgs(Integer id, String name, String sex, Integer age, String addr, Double salary);}八 、Student实体类 (类实例方法引用)@Data@AllArgsConstructor@NoArgsConstructorpublic class Student { private Integer id; private String name; private String sex; private Integer age; private String addr; private Double salary; public int classCompareStudentByAge(Student student) { return this.getAge() - student.getAge(); } public int classCompareStudentByName(Student student) { return this.getName().compareToIgnoreCase(student.getName()); }}九、 测试结果 . ____ _ __ _ _ /\ / ’ __ _ () __ __ _ \ \ \ ( ( )__ | ‘_ | ‘| | ‘ / ` | \ \ \ \ \/ )| |)| | | | | || (| | ) ) ) ) ’ || .__|| ||| |_, | / / / / =========||==============|/=//// :: Spring Boot :: (v2.1.2.RELEASE)2019-02-02 17:04:20.851 INFO 16876 — [ main] c.j.d.j.MethodReference.MethodReference : Starting MethodReference on DESKTOP-87RMBG4 with PID 16876 (started by 46250 in E:\IdeaProjects\design)2019-02-02 17:04:20.852 INFO 16876 — [ main] c.j.d.j.MethodReference.MethodReference : No active profile set, falling back to default profiles: default2019-02-02 17:04:21.422 INFO 16876 — [ main] c.j.d.j.MethodReference.MethodReference : Started MethodReference in 0.878 seconds (JVM running for 1.682)—————————————集合遍历 LambdaKiritoLoveAsuna—————————————集合遍历 MethodReferenceKiritoLoveAsuna————————————— 静态方法引用 按年龄排序Student(id=5, name=Alice, sex=Female, age=14, addr=Alicization, salary=9.99999999E8)Student(id=4, name=Yuuki, sex=Female, age=15, addr=Alfheim Online, salary=9.99999999E8)Student(id=3, name=Sinon, sex=Female, age=16, addr=Gun Gale Online, salary=9.99999999E8)Student(id=2, name=Asuna, sex=Female, age=17, addr=Sword Art Online, salary=9.99999999E8)Student(id=1, name=Kirito, sex=Male, age=18, addr=Sword Art Online, salary=9.99999999E8)————————————— 静态方法引用 按姓名排序Student(id=5, name=Alice, sex=Female, age=14, addr=Alicization, salary=9.99999999E8)Student(id=2, name=Asuna, sex=Female, age=17, addr=Sword Art Online, salary=9.99999999E8)Student(id=1, name=Kirito, sex=Male, age=18, addr=Sword Art Online, salary=9.99999999E8)Student(id=3, name=Sinon, sex=Female, age=16, addr=Gun Gale Online, salary=9.99999999E8)Student(id=4, name=Yuuki, sex=Female, age=15, addr=Alfheim Online, salary=9.99999999E8)————————————— 静态方法引用 按年龄排序Student(id=5, name=Alice, sex=Female, age=14, addr=Alicization, salary=9.99999999E8)Student(id=4, name=Yuuki, sex=Female, age=15, addr=Alfheim Online, salary=9.99999999E8)Student(id=3, name=Sinon, sex=Female, age=16, addr=Gun Gale Online, salary=9.99999999E8)Student(id=2, name=Asuna, sex=Female, age=17, addr=Sword Art Online, salary=9.99999999E8)Student(id=1, name=Kirito, sex=Male, age=18, addr=Sword Art Online, salary=9.99999999E8)————————————— 对象实例方法引用 按姓名排序Student(id=5, name=Alice, sex=Female, age=14, addr=Alicization, salary=9.99999999E8)Student(id=2, name=Asuna, sex=Female, age=17, addr=Sword Art Online, salary=9.99999999E8)Student(id=1, name=Kirito, sex=Male, age=18, addr=Sword Art Online, salary=9.99999999E8)Student(id=3, name=Sinon, sex=Female, age=16, addr=Gun Gale Online, salary=9.99999999E8)Student(id=4, name=Yuuki, sex=Female, age=15, addr=Alfheim Online, salary=9.99999999E8)————————————— 类实例方法引用 按年龄排序Student(id=5, name=Alice, sex=Female, age=14, addr=Alicization, salary=9.99999999E8)Student(id=4, name=Yuuki, sex=Female, age=15, addr=Alfheim Online, salary=9.99999999E8)Student(id=3, name=Sinon, sex=Female, age=16, addr=Gun Gale Online, salary=9.99999999E8)Student(id=2, name=Asuna, sex=Female, age=17, addr=Sword Art Online, salary=9.99999999E8)Student(id=1, name=Kirito, sex=Male, age=18, addr=Sword Art Online, salary=9.99999999E8)————————————— 类实例方法引用 按姓名排序Student(id=5, name=Alice, sex=Female, age=14, addr=Alicization, salary=9.99999999E8)Student(id=2, name=Asuna, sex=Female, age=17, addr=Sword Art Online, salary=9.99999999E8)Student(id=1, name=Kirito, sex=Male, age=18, addr=Sword Art Online, salary=9.99999999E8)Student(id=3, name=Sinon, sex=Female, age=16, addr=Gun Gale Online, salary=9.99999999E8)Student(id=4, name=Yuuki, sex=Female, age=15, addr=Alfheim Online, salary=9.99999999E8)————————————— 类实例方法引用 容易理解的 字符串排序AliceAsunakiritoSinonYuuki—————————————利用无参构造方法构造studentNoArgs对象Student(id=null, name=null, sex=null, age=null, addr=null, salary=null)—————————————利用全参构造方法构造studentNoArgs对象Student(id=6, name=Silica, sex=Female, age=10, addr=Sword Art Online, salary=9.99999999E8) ...

February 2, 2019 · 4 min · jiezi

深入理解 lambda表达式 与 Optional Null 源码解析(Java11 三)

import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.test.context.junit4.SpringRunner;import java.util.*;import java.util.function.Function;import java.util.function.Supplier;import java.util.stream.Collectors;import java.util.stream.Stream;/** * @author 陈杨 /@RunWith(SpringRunner.class)@SpringBootTestpublic class OptionalTest { @Test public void testOptional() {一、Optional出现的缘由/ * A container object which may or may not contain a non-{@code null} value. * * 一个装泛型为T的 值容器 可以包含Null 以规避 空指针异常 * public final class Optional<T> /二、深入理解 Value-based Classes/ * Value-based Classes * * https://docs.oracle.com/javase/8/docs/api/java/lang/doc-files/ValueBased.html * * final immutable (但里面可以包含指向 可变对象的引用) * 具有equals、hashCode和toString的实现 仅从实例的状态计算 而不是从其标识或任何其他对象或变量的状态计算 * 不使用身份敏感的操作,例如实例之间的引用相等(==) 实例的hashCode,或实例的内部锁(intrinsic lock)同步 * 判断是否相等 仅比较equals()方法 而非对象的引用(==) * 没有可访问的构造函数 通过工厂方法实例化,不保证实例创建的一致性(不一定是单例) * * 基于值的对象 没有public的构造方法 比较值是否相等(不比较引用) /三、Optional容器的构造// private static final Optional<?> EMPTY = new Optional<>();// private final T value;// Constructs an empty instance.// private Optional() { this.value = null; }/ * Constructs an instance with the described value. * * private Optional(T value) { this.value = Objects.requireNonNull(value); } // * Returns an empty {@code Optional} instance. No value is present for this {@code Optional}. * * public static<T> Optional<T> empty() { * @SuppressWarnings(“unchecked”) * Optional<T> t = (Optional<T>) EMPTY; * return t; * } /Optional<List<String>> empty = Optional.empty();/ 构造一个容器里不为 null 的容器对象 * * public static <T> Optional<T> of(T value) { return new Optional<>(value); } /Optional<List<String>> optional = Optional.of(Arrays.asList(“Kirito”, “Love”, “Asuna”));/ 构造一个容器里可能为 null 的容器对象 * * public static <T> Optional<T> ofNullable(T value) { return value == null ? empty() : of(value); } /四、普通方法/ 获取容器中的所有值 * public T get() { * if (value == null) { * throw new NoSuchElementException(“No value present”); * } * return value; * } /System.out.println("—————————————\n");System.out.println(“optional容器中存在的值:” + optional.get());// 判断 容器中存在值 返回true// public boolean isPresent() { return value != null; }System.out.println("—————————————\n");System.out.println(“optional容器中存在值:” + optional.isPresent());System.out.println(“empty容器中存在值:” + empty.isPresent());// 判断 容器中不存在值 返回true// @since 11// public boolean isEmpty() { return value == null; }System.out.println("—————————————\n");System.out.println(“optional容器中不存在值:” + optional.isEmpty());System.out.println(“empty容器中不存在值:” + empty.isEmpty());五、高级拓展1、ifPresent(Consumer)/ * 如果存在 value 对 value 进行一个 Consumer消费 * public void ifPresent(Consumer<? super T> action) { * if (value != null) { * action.accept(value); * } * } * /System.out.println("—————————————\n");System.out.println(“optional容器中存在值就进行Consumer消费(打印输出)”);optional.ifPresent(System.out::println);2、ifPresentOrElse(Consumer)/ 如果存在 value 对 value 进行一个 Consumer消费 不存在 执行emptyAction(empty-based action) * @since 9 * public void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction) { * if (value != null) { * action.accept(value); * } else { * emptyAction.run(); * } * } /System.out.println("—————————————\n");System.out.println(“容器中存在值就打印值,不存在打印 hello world”);optional.ifPresentOrElse(System.out::println, () -> System.out.println(“hello world”));empty.ifPresentOrElse(System.out::println, () -> System.out.println(“hello world”));3、filter(Predicate)/ * 如果存在value 且符合预期predicate 则对 value 进行预期操作predicate.test(value) 否则返回empty * public Optional<T> filter(Predicate<? super T> predicate) { * Objects.requireNonNull(predicate); * if (!isPresent()) { * return this; * } else { * return predicate.test(value) ? this : empty(); * } * } /System.out.println("—————————————\n");System.out.println(“遍历集合元素”);optional.filter(strings -> { strings.forEach(System.out::println); return true;});4、or(Supplier)/ * 如果存在value 则返回value 否则使用supplier接口的get()方法 构造出一个Optional * @since 9 * public Optional<T> or(Supplier<? extends Optional<? extends T>> supplier) { * Objects.requireNonNull(supplier); * if (isPresent()) { * return this; * } else { * @SuppressWarnings(“unchecked”) * Optional<T> r = (Optional<T>) supplier.get(); * return Objects.requireNonNull(r); * } * } /System.out.println("—————————————\n");Supplier<Optional<List<String>>> sup = () -> Optional.ofNullable(Arrays.asList(“Optional”, “or”, “supplier”));System.out.println(empty.or(sup));5、Stream.of(value)/ * 如果存在value 则返回Stream.of(value) 否则返回一个Stream.empty() * @since 9 * public Stream<T> stream() { * if (!isPresent()) { * return Stream.empty(); * } else { * return Stream.of(value); * } * } /System.out.println("—————————————\n");System.out.println(“以stream流 遍历optional容器内的值”);Stream<List<String>> stream = Stream.of(optional.get());stream.forEach(System.out::println);6、orElse(T other)/ * 如果存在value 则返回value 否则返回T other * public T orElse(T other) { * return value != null ? value : other; * } /System.out.println("—————————————\n");System.out.println(" 容器中存在值就返回值 不存在就返回{"hello","world"}");System.out.println(empty.orElse(Arrays.asList(“hello”, “world”)));7、orElseGet(Supplier)/ * 如果存在value 则返回value 否则返回Supplier接口实现 * public T orElseGet(Supplier<? extends T> supplier) { * return value != null ? value : supplier.get(); * } /System.out.println("—————————————\n");Supplier<List<String>> listSupplier = () -> Arrays.asList(“do”, “orElseGet”);System.out.println(empty.orElseGet(listSupplier));8、orElseThrow/ * 如果存在value 则返回value 否则抛出异常NoSuchElementException * @since 10 * public T orElseThrow() { * if (value == null) { * throw new NoSuchElementException(“No value present”); * } * return value; * } /System.out.println("—————————————\n");System.out.println(" 容器中存在值就返回值 不存在就返回NoSuchElementException");System.out.println(optional.orElseThrow());try { System.out.println(empty.orElseThrow());} catch (NoSuchElementException e) { System.out.println(" NoSuchElementException —> No value present");}9、orElseThrow(Supplier)/ * 如果存在value 则返回value 否则使用Supplier接口生成一个被抛出的exceptionSupplier –>exception * public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X { * if (value != null) { * return value; * } else { * throw exceptionSupplier.get(); * } * } /System.out.println("—————————————\n");Supplier<NoSuchElementException> noSuchElementException = NoSuchElementException::new;try { System.out.println(empty.orElseThrow(noSuchElementException));} catch (NoSuchElementException e) { System.out.println(" Supplier NoSuchElementException —> No value present");}10、map(Function)/ * * 如果存在value 则返回value并作为mapper的输入 将其输出作为新的value存放至Optional 否则返回一个null的Optional * 如果经过mapper 后得到的结果为null 返回一个null的Optional * mapper函数若为null 则抛出NullPointerException * map:对集合中每个元素进行操作 * * * public <U> Optional<U> map(Function<? super T, ? extends U> mapper) { * Objects.requireNonNull(mapper); * if (!isPresent()) { * return empty(); * } else { * return Optional.ofNullable(mapper.apply(value)); * } * } /System.out.println("—————————————\n");Function<List<String>, List<String>> function = up -> up.stream().map(String::toUpperCase).collect(Collectors.toList());Optional<List<String>> o = optional.map(function);System.out.println(o.get());11、flatMap(Function) / * 如果存在value 则返回value并作为mapper的输入 将其输出作为新的value存放至Optional 否则返回一个null的Optional * 如果经过mapper 后得到的结果为null 返回一个null的Optional * mapper函数若为null 则抛出NullPointerException * * 与map的方法的区别: * map * * return Optional.ofNullable(mapper.apply(value)); * * flatMap * * Optional<U> r = (Optional<U>) mapper.apply(value); * return Objects.requireNonNull(r); * flatMap:对集合中每个元素进行操作然后再扁平化 * * * public <U> Optional<U> flatMap(Function<? super T, ? extends Optional<? extends U>> mapper) { * Objects.requireNonNull(mapper); * if (!isPresent()) { * return empty(); * } else { * @SuppressWarnings(“unchecked”) * Optional<U> r = (Optional<U>) mapper.apply(value); * return Objects.requireNonNull(r); * } * } */ System.out.println("—————————————\n"); Function<List<String>, Optional<List<String>>> func = up -> Optional.of(up.stream().map(String::toUpperCase).collect(Collectors.toList())); Optional<List<String>> u = optional.flatMap(func); System.out.println(u.get()); }}六、测试 . ____ _ __ _ _ /\ / ’ __ _ () __ __ _ \ \ \ ( ( )__ | ‘_ | ‘| | ‘ / ` | \ \ \ \ \/ )| |)| | | | | || (| | ) ) ) ) ’ || .__|| ||| |_, | / / / / =========||==============|/=//// :: Spring Boot :: (v2.1.2.RELEASE)2019-02-01 18:29:34.870 INFO 17140 — [ main] com.java.design.java8.OptionalTest : Starting OptionalTest on DESKTOP-87RMBG4 with PID 17140 (started by 46250 in E:\IdeaProjects\design)2019-02-01 18:29:34.871 INFO 17140 — [ main] com.java.design.java8.OptionalTest : No active profile set, falling back to default profiles: default2019-02-01 18:29:35.437 INFO 17140 — [ main] com.java.design.java8.OptionalTest : Started OptionalTest in 0.775 seconds (JVM running for 1.574)—————————————optional容器中存在的值:[Kirito, Love, Asuna]—————————————optional容器中存在值:trueempty容器中存在值:false—————————————optional容器中不存在值:falseempty容器中不存在值:true—————————————optional容器中存在值就进行Consumer消费(打印输出)[Kirito, Love, Asuna]—————————————容器中存在值就打印值,不存在打印 hello world[Kirito, Love, Asuna]hello world—————————————遍历集合元素KiritoLoveAsuna—————————————Optional[[Optional, or, supplier]]—————————————以stream流 遍历optional容器内的值[Kirito, Love, Asuna]————————————— 容器中存在值就返回值 不存在就返回{“hello”,“world”}[hello, world]—————————————[do, orElseGet]————————————— 容器中存在值就返回值 不存在就返回NoSuchElementException[Kirito, Love, Asuna] NoSuchElementException —> No value present————————————— Supplier NoSuchElementException —> No value present—————————————[KIRITO, LOVE, ASUNA]—————————————[KIRITO, LOVE, ASUNA]Process finished with exit code 0 ...

February 1, 2019 · 5 min · jiezi

2018年第51周-JAVA虚拟机内存模型及垃圾回收机制(概要)

JAVA内存区域运行时数据区域根据《Java虚拟机规范(Java SE 7版)》的规定,Java虚拟机管理的内存将会包括以下运行时数据区域:1.程序计数器 2.Java虚拟机栈(在HotSpot虚拟机中本地方法栈和虚拟机栈合二为一) 3.Java堆 4.方法区(包括运行时常量池) ,存放的是Class的相关信息和常量,又称“永生代” 5.直接内存(NIO使用的)程序计数器程序计数器(Program Counter Register)是当前线程所执行的字节码的行号指示器。各个线程之间的计数器互不影响,所以这块内存是线程私有的内存。Java虚拟机栈Java虚拟机栈(Java Virtual Machine Stacks)也是线程私有,生命周期与线程相同。是Java方法执行的内存模型,每个方法执行的同时会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出等信息。每个方法从调用执行到执行完毕的过程,就是对应这栈帧的一次入栈和出栈过程。方法区方法区(Method Area)是线程共享的内存区域,用于存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。Java堆这就是重头戏了,是Java虚拟机所管理的内存中最大的一块,也是所有线程共享的一块内存。 此内存存放对象实例,所有也是垃圾回收的主要区域。采用分代收集算法,简单说就是分为新生代和老年代。 新生代又根据对象朝生暮死的特性,分为Eden空间、两块Survivor空间(From空间和To空间)。From空间和To空间是相对的,两者是两快大小相同的内存。新生代垃圾回收器采用复制算法(Copying)来回收新生代,新生的对象都会分配到Eden空间,当回收时,会将Eden空间和一块Survivor空间的存活对象,复制到一块Survivor空间(假设是To空间),此时Eden空间和From空间就会被直接清空,如果To空间不够分配内存给存活的空间,则存活的对象会直接进入老年代的内存空间。新生代的回收频率高,但每次回收的耗时短,这个回收过程称为Minor GC。HotSpot虚拟机默认Eden空间和一块Survivor空间是8:1老年代,Java虚拟机管理的内存空间,除去新生代、虚拟机栈、方法区等内存,就是属于老年代。老年代其特点就是对象的存活率很高,甚至100%,所以使用复制算法,会严重浪费内存。所以根据老年代的特点,首先标志所有需要回收的对象,在标记完成后,将所有存活的对象都向一端移动,然后直接清理掉边界以外的内存。这就是标志-整理(Mark-Compact)算法,也有称为标志压缩法,其实是一个东西。 老年代的回收频率低,但每次回收的耗时长,这个回收过程称为Major GC,也粗略认为是Full GC。直接内存直接内存(Direct Memory)并不是Java虚拟机运行时数据区的一部分。在JDK1.4引入了NIO,引入了基于通道(Channel)和缓冲区(Buffer)的I/O方式,它可以使用Native函数直接分配堆外内存。其GC回收也是通过Full GC进行回收。各区域的内存溢出情况Java堆的异常是://可通过配置参数-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=../logs/dump.hprof 把虚拟机在出现内存溢出时Dump当前的内存堆转储存快照java.lang.OutOfMemoryError: Java heap spaceJava虚拟机栈有两种异常分别是: StackOverflowError异常//虚拟机配置-Xss128k来设置虚拟机栈内存容量//stack深度长度为:1000Exception in thread “main” java.lang.StackOverflowError at com.jc.vm.StackOverflowDemo.stackLeek(StackOverflowDemo.java:7) …OutOfMemoryError异常java.lang.OutOfMemoryError: unable to create new native thread虚拟栈OutOfMemoryError异常情况需说明下: 虚拟机提供了参数控制Java堆和方法区的这两部分的内存的最大值。而操作系统分配给每个进程的内存是有限制的,譬如32位的Windows限制是2GB,则2GB减去Xmx(最大堆容量),再减去MaxPermSize(最大方法区容量),程序计数器消耗内存很小,可以忽略。如果虚拟机进程本身耗费的内存不计算在内,则剩下的内存就是由Java虚拟机栈“瓜分”了。每个线程分配到的栈容量越大,可以建立的线程数就自然减少,建立线程时容就越容易把剩下的内存耗尽。 如果是建立过多的线程导致的内存溢出,在不减少线程数或更换64位虚拟机的情况下,就只能通过减少最大堆和减少栈容量来换取更多的线程。方法区的异常是: 能导致内存溢出,也就是常量变多或Class变多,可以使用CGLib动态创建类来造成方法区内存溢出//在JDK7及以下版本,我们可以通过-XX:PermSize和-XX:MaxPermSize限制方法区大小//注:Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=10M; support was removed in 8.0//Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=10M; support was removed in 8.0//JDK8已将参数-XX:PermSize和-XX:MaxPermSize移除了Exception in thread “main” java.lang.OutOfMemoryError: PermGen space …直接内存的异常:直接内存是不受Java堆大小的限制,不过可以JDK参数-XX: MaxDirectMemorySize(默认与-Xmx大小一样),如果,大于次参数的值,则会抛出java.langOfMemoryError,实际没有真正向操作系统申请分配内存,而是通过计算得出内存无法分配。对象的内存分配算法指针碰撞(Bump the Pointer):这种分配算法指Java堆中内存是绝对规整的,所有用过的内存都放在一边,空闲的放在一边,中间放着一个指针作为分界点的指示器,那所分配内存就仅仅是那个指针向空闲空间那边挪动一段与对象大小想等的距离。 缺点是处理并发不好。空闲列表(Bump the Pointer):这种分配算法指虚拟机维护一个列表,记录哪些内存块是可用的,在分配的时候从列表中找到一块足够大的空间划分给对象实例,并更新列表上的记录。缺点是造成碎片比较多选择哪种分配算法,是根据Java堆是否规整来决定,所以不同垃圾收集器使用不同的分配算法:Serial、ParNew等带Compact过程的收集器,采用的分配算法就是指针碰撞。CMS这种基于Mark-Sweep算法的收集器时,通常采用空闲列表。对象访问方式对象的访问方式分为使用句柄和直接指针(HotSpot使用直接指针)。 两个访问方式各有好处,使用句柄访问的最大好处就是reference中存储的是稳定的句柄地址,在对象移动时(垃圾回收)只需改变句柄中的数据指针即可。 而直接指针访问方式的好处就是速度快,reference直接指向数据,比使用句柄,节省了一次指针定位时间,由于对象的访问是非常频繁,所以能节省很多时间。对象是否存活判断算法引用计数(Reference Counting),此算法实现简单,判定效率高。如微软公司的COM(Component Object Model)技术、使用AcionScript3的FlashPlayer、Python语言和Squirrel都使用引用计数算法进行内存管理。缺点,很难解决对象之间相互循环引用的问题。 可达性分析,此算法基本思路就是通过一系列的称为“GC Roots”的对象作为起始点,从这些检点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连(用图论的话:从GC Roots到这个对象不可达)时,则证明对象是不可用的。在Java语言中,可作为GC Roots的对象包括下面几种: 虚拟机栈中引用的对象。方法区中类静态属性引用的对象。方法区中常量引用的对象。本地方法栈中JNI(即一般说的Native方法)引用的对象。垃圾收集算法标记-清除(Mark-Sweep)算法,此算法分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。缺点有两个:一是效率问题;另一个是空间问题,标记清楚后会产生大量不连续的内存碎片。 复制(Copy)算法,是当前主流垃圾回收的思想(针对新生代的内存区域),此算法就将可用的内存容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存在的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。缺点是代价内存耗费比较多。 但专门研究表明, 新生代中的对象98%是“朝生夕死”的,所以并不需要1:1的比例来划分内存,而是将内存分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden和其中一块Survivor。当回收时,将Eden和Survivor中还存活的对象一次性复制到另外一块Survivor上,最后清理掉Eden和刚才用过的Survivor空间。 HotSpot默认Eden和Survivor的大小比例是8:1,也就是新生代中可用内存空间为整个新生代容量的90%,只有10%的内存会被“浪费”。 当Survivor空间不够用时,需要依赖其他内存(老年代)进行分配担保(Handle Promotion),所以这种垃圾收集算法如果不想浪费50%空间,就需要有额外的空间进行分配担保以应对所有对象都100%存活的极端情况,所以老年代一般不能直接选用这种算法。 标记-整理(Mark-Compact)算法,这是根据老年代的特点提出一种算法,标记过程仍与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。分代收集算法,此算法是根据对象存活周期的不同将内存划分为几块。一般的把Java堆分为新生代和老年代。在新生代中,每次垃圾收集时都发现大批对象死去,只有少量存活,那就是选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记-清理”或者“标记整理”算法进行回收。垃圾收集器如果说垃圾收集算法是内存回收的方法论,那么垃圾回收器就是内存回收的具体实现。图展示了7种作用不同分代的收集器,如果两个收集器之间存在连线,就说明它们可以搭配使用。其中?是G1收集器Serial收集器(新生代)这个收集器时一个单线程,独占式的收集器,它进行垃圾收集时,必须暂停其他所有的工作线程,直到它收集结束。这是JDK1.3时之前新生代唯一的选择。 参数-XX:UseSerialGC,新生代使用Serial收集器,老年代使用Serial Old收集器。虚拟机在Client模式下,默认使用该收集器作为新生代收集器。使用复制算法。ParNew收集器(新生代)ParNew收集器其实就是Serial收集器的多线程版本。由于CMS作为老年代的收集器,无法与新生代的PS收集器配合工作。参数-XX:+UseConcMarkSweepGC,新生代就是默认使用ParNew收集器,老年代使用CMS收集器。参数-XX:+UseParNewGC,新生代使用ParNew收集器,老年代使用Serial Old收集器。需考虑-XX:ParallelGCThreads来控制垃圾收集的线程数。 使用复制算法。Parallel Scavenge收集器(新生代)PS收集器跟ParNew收集器一样,都是多线程,独占式的收集器这个收集器与其他收集器关注点不同,CMS等收集器关注点是尽可能地缩短垃圾收集时用户线程的停顿时间,而PS收集器的目标则是达到一个可控制的吞吐量(Throughput)。吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)。关注吞吐量的收集器适合后台运算。 可控制吞吐量参数-XX:+UseParallelGC,新生代使用PS收集器,老年代使用Serial Old收集器。参数-XX:+UseParallelOldGC,新生代使用PS收集器,老年代使用Parallel Old收集器。使用复制算法。Serial Old收集器(老年代)单线程,独占式收集器。在Server模式下,主要有两大用途:一种用途是JDK5以及之前的版本中于PS收集器搭配使用,另一种用途是作为CMS收集器的后备预案,在并发收集发生Concurrent Mode Failure时使用。虚拟机在Client模式下,默认使用该收集器作为老生代收集器。参数-XX:UseSerialGC,新生代使用Serial收集器,老年代使用Serial Old收集器。参数-XX:+UseParNewGC,新生代使用ParNew收集器,老年代使用Serial Old收集器。参数-XX:+UseParallelGC,新生代使用PS收集器,老年代使用Serial Old收集器。使用标志压缩算法。Parallel Old收集器(老年代)多线程,独占式收集器JDK6才提供的,在此之前PS收集器只能于Serial Old收集器搭配,效果并不明显,且无法和CMS搭配,所以才诞生Parallel Old收集器。 在注重吞吐量以及CPU资源敏感的场合,都可以优先考虑Parallel Scavenge加Parallel Old收集器。参数-XX:+UseParallelOldGC,新生代使用PS收集器,老年代使用Parallel Old收集器。使用标志压缩算法。CMS收集器(老年代)多线程,整体上不是独占式收集器,只有初始标识和重新标志阶段是独占系统资源的。CMS(Concurrent Mark Sweep)收集器时一种以获取最短回收停顿时间为目标的收集器。简单的说,此收集器关注点是低停顿时间。是只有在初始标识和重新标志阶段是STW,其他阶段是可以与应用线程一起执行的。 从名字包含“ Mark Sweep”就知道使用的收集算法是“标记——清除”算法。四步骤: 1.初始标记(CMS initial mark) ,需要STW2.并发标记(CMS concurrent mark) 3.重新标记(CMS remark) ,需要STW4.并发清除(CMS concurrent sweep) 优点:并发收集、低停顿 目前很大一部分的Java应用集中在互联网站或者B/S系统的服务端上,这类应用尤其重视服务的响应时间,希望系统停顿时间最短,以给用户带来较好的体验。CMS收集器就非常适合。如我所在过的一家互联网公司在64位的jdk情况下使用CMS收集器缺点: 1.CMS收集器对CPU资源敏感 2.CMS收集器无法处理浮动垃圾(Floating Garbage,指的是CMS在整个过程基本都不STW,所以应用程序还在不断产生垃圾,这些垃圾称为浮动垃圾),则需通过-XX:CMSInitiatingOccupancyFraction来配置老年代内存达到多少时触发CMS收集。JDK5默认收68%,JDK6默认是92%。要是CMS运行期间预留的内存无法满足程序需要,就会出现一次“Concurrent Mode Failure”失败,这时虚拟机将启动后备预案:临时启用Serial Old收集器来重新进行老年代的垃圾收集。所以-XX:CMSInitiatingOccupancyFraction配置越高,就很容易导致大量的“Concurrent Mode Failure”失败,性能反而降低。如我所在过的一家互联网公司在64位的jdk情况下使用-XX:CMSInitiatingOccupancyFraction=70 3.CMS是基于“标记——清除”算法实现的收集器,则会产生大量空间碎片。则需配置个参数-XX:+UserCMSCompactAtFullCollection来开启碎片整理。但依然会造成停顿时间太长,所以虚拟机设计者提供了-XX:CMSFullGCsBeforeCompaction,来控制执行多少次不压缩的Full GC后进行带压缩的Full GC,默认值为0(表示每次进入Full GC时都进行碎片压缩) 参数-XX:+UseConcMarkSweepGC,新生代就是默认使用ParNew收集器,老年代使用CMS收集器。使用标志清除算法。G1收集器G1(Garbage-First)收集器是当今收集器技术发展的最前沿成果之一。葱JDK 6u14开始就有Early Access版本的G1收集器供开发人员实验、试用,由此开始G1收集器的“Experimental”状态持续了数年时间,直至JDK 7u4,Sun公司才认为它达到足够成熟的商用程度,移除了“Experimental”的标识。未来可以替换JDK 1.5中发布的CMS收集器。G1具备一下特点: 1.并行并发 2.分代收集 3.空间整合,分Region去处理,类似于并发的map 4.可预测的停顿G1收集器运作大致可分为以下步骤: 1.初始标记(Initial Marking)2.并发标记(Concurrent Marking)3.最终标记(Final Marking)4.筛选标记(Live Data Counting and Evacuation)附录并行(Parallel): 指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态。 并发(Concurrent): 指用户线程与垃圾收集线程同事执行(但不一定是并行的,可能会交替执行),用户程序在继续运行,而垃圾收集程序运行于另一个CPU上。参考:https://bugs.java.com/bugdata…《深入理解Java虚拟机》《实战Java虚拟机》 ...

December 24, 2018 · 1 min · jiezi

猫头鹰的深夜翻译:Java WeakHashMap

本文简介WeakHashMap类概览WeakHashMap类构造器总结WeakHashMap类构造方法WeakHasjMap类使用举例1. WeakHashMap类概览WeakHashMap是一个实现了Map接口,并且键为weak型的哈希表。WeakHashMap中的条目不再被正常使用时,会被自动删除。它的键值均支持null。这个类类似于HashMap类,也具有初始容量和负载因子这样的效率参数。和绝大多数的集合类一样,这个类不是同步的。需要使用Collections.synchronizedMap方法来进行同步控制。弱引用–如果一个对象只有一个弱引用,那么垃圾回收期可以随时收回该对象的内存。它不需要等到系统内存不足时才回收。通常,它的内存会在下一次垃圾收集器运行时释放。2. WeakHashMap的构造器WeakHashMap(): 构造一个新的,空的WeakHashMap,初始容量为16,负载因子为0.75WeakHashMap(int initialCapacity): 构造一个新的,空的WeakHashMap, 初始容量为initialCapacity,负载因子为0.75WeakHashMap(int initialCapacity, float loadFactor): 构造一个新的,空的WeakHashMap, 初始容量为initialCapacity,负载因子为loadFactorWeakHashMap(Map<? extends K, ? extends V> m): 利用已有的map构造WeakHashMap3. WeakHashMap类的方法void clear(): 删除所有的条目boolean containsKey(Object key): 如果有该键,返回trueboolean containsValue(Object value): 如果有一个或多个value值,返回trueSet< Map.Entry<K,V>>entrySet(): 返回键值视图void forEach(BiConsumer<? super K,? super V> action): 对此映射中的每个条目执行给定操作,直到处理完所有条目或操作引发异常。V get(Object key): 返回指定键映射到的值,如果此映射不包含键的映射,则返回null。boolean isEmpty(): 如果此映射不包含键 - 值映射,则返回true。4. WeakHashMap类使用示例import java.util.Map;import java.util.Map.Entry;import java.util.WeakHashMap;public class WeakHashMapExample { public static void main(final String[] args) { final Map<Key, Project> map = new WeakHashMap<>(); Key key1 = new Key(“ACTIVE”); final Key key2 = new Key(“INACTIVE”); map.put(key1, new Project(100, “Customer Management System”, “Customer Management System”)); map.put(key2, new Project(200, “Employee Management System”, “Employee Management System”)); key1 = null; System.gc(); for (final Entry<Key, Project> entry : map.entrySet()) { System.out.println(entry.getKey().getKey() + " " + entry.getValue()); } }}class Key { private String key; public Key(final String key) { super(); this.key = key; } public String getKey() { return key; } public void setKey(final String key) { this.key = key; }}输出:INACTIVE [project id : 200, project name : Employee Management System, project desc : Employee Management System ] ...

December 7, 2018 · 1 min · jiezi

猫头鹰的深夜翻译:JDK Vs. JRE Vs. JVM之间的区别

什么是Java Development Kit (JDK)?JDK通常用来开发Java应用和插件。基本上可以认为是一个软件开发环境。JDK包含Java Runtime Environment(JRE),JRE包含加载器/解释器,编译器(javac),文档生成器(Javadoc),打包功能(jar)和其它在开发中所需要功能:加载代码校验代码执行代码提供运行时环境什么是Java Runtime Environment(JRE)Java Runtime Environment(JRE)又称为Java RTE。JRE中包含核心类和支持文件。它还包含JVM。JVM会提供运行时环境。确定JVM运行的特定类型。其类型主要由Sun和其它的几个机构提供。其实现是一个满足JVM特定前提条件的客户端程序。运行时实例无论何时运行Java类,都会产生JVM。JDK一个物理存在的工具包。它包含JRE和其他工具。什么是Java Virtual Machine(JVM)JVM为执行Java字节码提供一个运行环境。它是一个抽象的独立于平台运行的机器。它的实现主要包含三个部分,描述JVM实现规格的文档,具体实现和满足JVM要求的计算机程序以及实例(具体执行Java字节码)。JVM的主要任务包括:加载代码校验代码执行代码提供运行时环境JDK, JRE和JVM之间的区别JRE的组成部署机制:Java Web Start, Java插件等UI工具包:AWT,Swing,Java2D等集成库:IDL,JDBC,RMI等其它基础库:I/O,JNI,JMX等Lang和utils基础库:lang,util,格式化,序列化,打包等JVM:Java HotSpot客户端和服务端虚拟机JRE功能为了了解JRE的功能,可以看一下是如何加载Example.class这个类的。该类先被转化为一组字节码并放入.class文件中。Java ClassLoaderClassLoader将执行程序所需的每个重要类放入堆栈中。它通过命名系统来提供彼此之间的安全性。源码可以来自于硬盘,系统以及其它来源。Java 字节码校验器JVM通过字节码校验器检查格式并找出非法代码。校验器确JVM执行代码时能够够快,以及这段代码不会损害现存的框架。Java解释器解释器有两个功能:执行字节码正确调用隐藏的设备

November 24, 2018 · 1 min · jiezi