-
作者:冯世杰编者按:Java Flight Recorder(简称为JFR)曾经是Oracle JDK商业版的附属组件,在JDK 11中被正式开始开源,后又被移植到JDK8中。JFR本身对运行期系统的侵入性很小,同时又能提供相对准确和丰富的运行期信息;合理使用该工具可以极大地提高工作效率。本文介绍JFR剖析的事件机制,希望能帮助大家从原理上理解JFR并正确使用JFR。本篇文章中的源码大部分来自openjdk8u262本文出发点是梳理 JFR 的事件机制, 侧重点在于理解而非应用使用上可以不要太过拘泥细节,可以具体问题具体分析。对于JFR我们有着怎样的预期它是一个辅助分析工具,我们希望借助它,尽可能低开销地收集运行时数据,从而辅助对JVM可能存在的故障、性能瓶颈进行分析。我们结合JFR的Goals来看:提供基于生成和消费数据作为事件的API提供缓存机制和二进制数据格式允许配置和过滤事件为OS、JVM、JDK库提供相应的事件从中,我们能粗略地获取这些信息 :事件以自描述的二进制形式(.jfr)被保存着事件中包含了数据,事件 ≈ 数据.jfr 文件 => read by some Provided API => 重现运行时数据 [ => 可视化]我们想尝试了解JFR的事件驱动机制,具体点就是回答几个问题:一个事件何时产生/启动监控? 经历了怎样的路径? 如何被保存? 保存到哪里? JFR是事件驱动的本节主要是一些前置信息 (假如你有所了解,可以快速浏览或者跳过本节内容): JVM行为基本都是Event,如类加载对应着Class Load Event, 垃圾回收对应GC Event;Event 主要由 timestamp, event name, additional info, data 这几部分组成。Event 收集四类事件的信息: Instant Event , 发生就收集(e.g. Thread Start ...)Duration Event,持续收集一段时间(e.g. GC Event ...)Timed Event , 收集超过指定时间的事件Sample Event,按频率采样以JFR的Class Load Event为例, 看看一个事件的结构。(共计 24 bytes)<memory address> : 98 80 80 00 87 02 95 ae e4 b2 92 03 a2 f7 ae 9a 94 02 02 01 8d 11 00 00Event Size : 98 80 80 00Event ID : 87 02TimeStamp : 95 ae e4 b2 92 03 Duration : a2 f7 ae 9a 94 02Thread ID : 02Stack trace ID : 01PayLoad(记录的数据,fields 取决于各个 Event 类型):加载的类 : 8d 11定义类的 ClassLoader : 00 初始化类的 ClassLoader : 00 多个线程都会产生Event,线程通过无锁(Lock-free)设计记录事件。线程将事件首先写入到 ThreadLocalBuffer(简称TLB), TLB被填满后,将被转存到 Global buffer(circular),对于较旧的数据,可以通过配置,选择丢弃或者写入磁盘,以便连续保存历史记录。示意图如下所示:注意:TLB、Global Buffer和磁盘文件中的事件记录不会相互备份,未及时转存的数据可能发生丢失,本文不会就这点展开阐述。前置内容已经交代清楚,接着回到正轨。一个事件的生命周期以下是枯燥乏味的一堆代码,但是不得不看。首先来看JFR的结构,如下图所示:肉眼可见的一堆钩子,这些hook用于记录对应的触发事件。我们简单地挑一个 Thread Start 的事件,关注一下它的整个被触发到被记录的过程。在线程创建并执行时会调用记录JFR事件,代码如下:可见当一个新的Java线程被创建时,只要开启了JFR, 那么就会执行上述代码; 接着看一下 on_thread_start 干了什么:在此,我们看到了一个事件EventThreadStart,并且在事件中设置信息后被提交。在 JEP 328中有一个更为简单直接例子,如下:无需太过关心其内容。我们只需关注这个事件生成的结构:这里的 EventType 定义于 jfrEventClass.hpp, 该文件是编译时生成的,简单贴一下生成逻辑,可以参考Makefile文件,如下 (同样无需在意太多细节): 回到主旋律,继续来看事件的结构和成员函数,如下:其中最为重要的成员函数是 JfrEvent::commit 方法,用于提交事件,代码如下.在函数中,最后一段代码, 也是核心所在,用于真正记录事件:这下,就可以很容易地和第1节的内容对应上了,特别是其中的事件模型的图片:小结用户是否可以自定义一个JFR事件?注意点有哪些?这里通过JEP 328里的例子(稍微有点改动),来展示如何自定义JFR事件。通过编译后直接执行如下命令:> java -XX:StartFlightRecording,filename=event.jfr Test可以得到如下日志信息:Started recording 1. No limit specified, using maxsize=250MB as default.Use jcmd 57980 JFR.dump name=1 to copy recording data to file.日志可以通过标准的API进行解析,下面通过一个简单代码解析上面生成的事件,代码如下:编译运行> java Viewer | less可以得到如下结果。相信此时你已经对JFR的事件机制有了个不错的感觉。实际上JFR的使用一般配合JMC[1]使用,在JMC中通过页面可以得到统计信息,更有助于判断系统的运行情况。后记如果遇到相关技术问题(包括不限于毕昇JDK),可以在论坛求助,也可以进入官网查找所有相关资源(包括二进制下载、代码仓库、使用教学、安装、学习资料等)。毕昇JDK社区每双周周二举行技术例会,同时有一个技术交流群讨论GCC、LLVM、JDK和V8等相关编译技术,感兴趣的同学可以添加如下微信小助手,回复Compiler入群。原文转载自 openEuler-Java Flight Recorder - 事件机制详解参考[1] https://adoptopenjdk.net/jmc.html
-
作者:宋尧飞编者按:笔者在AArch64中遇到一个G1 GC挂起,CPU利用率高达300%的案例。经过分析发现问题是由JVM的锁机制导致,该问题根因是并发编程中没有正确理解内存序导致。本文着重介绍JVM中Monitor的基本原理,同时演示了在什么情况下会触发该问题。希望通过本文的分析,读者能够了解到内存序对性能、正确性的影响,在并发编程时更加仔细。现象本案例是一个典型的弱内存模型案例,大致的现象就是AArch64平台上,业务挂死,而进程占用CPU持续维持在300%。配合top和gdb,可以看到是3个GC线程在offer_termination处陷入了死循环: 多个并行GC线程在Minor GC结束时调用offer_termination,在offer_termination中自旋等待其他并行GC线程到达该位置,才说明GC任务完成,可以终止。(关于并行任务的中止协议问题,可以参考相关论文,这里不做着重介绍。简单地说,在并行任务执行时,多个任务之间可能存在任务不均衡,所以JVM内部设计了任务均衡机制,同时必须设计任务终止的机制来保证多个任务都能完成,这里的offer_termination就是尝试终止任务)。在该案例中,部分GC线程完成自己的任务,等待其他的GC线程。此时出现挂起,很有可能是因为发生了死锁。所以问题很可能是由于那些尚未完成任务的GC线程上错误地使用锁。所以使用gdb观察了一下其他GC线程,发现其他GC线程全都阻塞在一把JVM的锁上: 而这把Monitor中的情况如下:cxq上积累了大量GC线程OnDeck记录的GC线程已经消失_owner记录的锁持有者为NULL分析在进一步分析前,首先普及一下JVM锁组件Monitor的基本原理,Monitor类主要包含4个核心字段:“Thread * volatile _owner;” 字段指向这把锁的持有线程“SplitWord _LockWord;” 字段被设计为1个机器字长,目的是为了确保操作时天然的原子性,它的最低位被设计为上锁标记位,而高位区域用来存放256字节对齐的竞争队列(cxq)地址“ParkEvent * volatile _EntryList;” 字段指向一个等待队列,跟cxq差别不大,个人理解只是为了缓解cxq的竞争压力而设计“ParkEvent * volatile _OnDeck;” 字段指向这把锁的法定继承人,同时最低位还充当了内部锁的角色接下来通过一组流程图来介绍加解锁的具体流程:上图是加锁的一个整体流程,大致分为3步:1. 首先走快速上锁流程,主要对应锁本身无人持有的最理想情况2. 接着是自旋上锁流程,这是预期将在短时间内获取锁的情况3. 最后是慢速上锁流程,申请者将会加入等待队列(cxq),然后进入睡眠,直到被唤醒后发现自己变成了法定继承者,于是进入自旋,直到完成上锁。 而且,基于性能考虑,整个上锁流程中的每一步几乎都做了“插队”的尝试:如上图代码中所示,“插队”的意思就是不经过排队(cxq),直接尝试置上锁标志位。 上图就是整个解锁流程了,显然真正的解锁操作在第二步中就已经完成了(意味着接下来时刻有“插队”现象发生),剩下的主要就是选出继承者的过程,大致分为以下几步:解锁线程首先需要将内部锁(_OnDeck)标记上锁从竞争队列(cxq)抽取所有等待者放入等待队列(_EntryList)_ EntryList取出头一个元素,写入_OnDeck的同时解除内部锁标记,这代表选出了继承者唤醒继承者当然伴随着整个解锁流程每一步的,还有对“插队”行为的处理。至此,JVM锁组件Monitor的原理就介绍到这里,再回归到问题本身,一个疑问就是_OnDeck上记录的继承者为何消失?作为继承者,既然已经消失在竞争队列和等待队列里,显然意味着它大概率已经持有锁、然后解锁走人了,所以问题很可能跟继承者选取过程有关。基于这种猜测,我们对相关代码着重进行了梳理,就发现了下图两处红框标记位置存在疑点,那就是在选继承者过程第3步中:写_ EntryList和写_OnDeck之间没有barrier来保证执行顺序,这可能出现_OnDeck先于_ EntryList写入的情况,一旦继承人提前持有锁,后果就可能非常糟糕… 这里贴了一张可能的问题场景:线程A处于解锁流程中,由于乱序,先写入了继承者同时解除内部锁线程B处于上锁流程,发现自己就是法定继承者后,立刻完成上锁线程B又迅速进入解锁流程,并从_EntryList中取出头元素(也就是线程B!)作为继承者写入_OnDeck,完成解锁走人线程A此时才更新_EntryList,然后唤醒继承者(也就是线程B!),完成解锁走人_OnDeck上的继承者线程B,实际已经完成加解锁离开,后续等待线程再也无法被唤醒正巧在社区的高版本上找到了一个相关的修复记录,这里贴出2个关键的代码片段: 上面这段代码位于慢速上锁流程,被唤醒后检查继承者是否是自己,修复后的代码在读_OnDeck时加了Load-Acquire的barrier。 上面这段代码位于解锁时选继承者流程,从_ EntryList取出头一个元素,写入_OnDeck的同时解除内部锁标记,修复后的代码在写_OnDeck时加了Store-Release的barrier。显然,围绕_OnDeck添加的这对One-way barrier可以确保:当继承者线程被唤醒时,该线程可以“看”到_EntryList已经被及时更新。总结在AArch64这种弱内存模型的平台上(关于内存序更多的知识在接下来的分享中会详细介绍),一旦涉及多线程对公共内存的每一次访问,必须反复确认是否需要通过barrier来严格保序,而且除非存在有效的依赖关系,否则barrier需要在读写端成对使用。后记如果遇到相关技术问题(包括不限于毕昇JDK),可以在论坛求助(目前毕昇JDK最新的官网http://bishengjdk.openeuler.org已经上线,可以进入官网查找所有相关资源,包括二进制下载、代码仓库、使用教学、安装、学习资料等)。毕昇JDK社区每双周周二举行技术例会,同时有一个技术交流群讨论GCC、LLVM、JDK和V8等相关编译技术,感兴趣的同学可以添加如下微信小助手,回复Compiler入群。原文转载自 openEuler-JVM 锁 bug 导致 G1 GC 挂起问题分析和解决
-
作者:袁含晨编者按:在升级JDK8U的小版本后(从8u74升级到8u202),遇到性能剧烈下降的问题(性能下降13倍)。该应用是一个非常简单的Web应用,且应用在JDK升级前后并无任何发布修改。通常来说JDK小版本升级都是问题修复,不影响功能和性能使用,而应用性能剧烈下降不一定是JVM代码层面的内部bug,有可能是默认选项变化等问题导致。对于这样明确由JDK引起的性能问题,该如何解决?最常见的方法是通过工具分析JVM执行过程,检查函数执行的情况是否发生变化,如果找到变化,则可以深入分析哪些因素引起了变化,并进一步得到根因。笔者使用perf工具分析JVM执行时的热点函数,并对出现问题的函数进行剖析,使用函数插桩来分析函数的执行次数,发现不同版本行为差异的根源,并找到了引起问题的根因。希望读者遇到性能问题时可以参照本文使用perf工具对问题进行定位。 工欲善其事,必先利其器。程序员在定位性能瓶颈的时候,要是有一个趁手的性能调优工具,能一针见血地指出程序的性能问题,可谓事半功倍。Linux中最常用的性能调优工具Perf(Linux系统原生提供的性能分析工具),使用perf先对应用(假设要采样的应用为JavaApp)进行采样,使用record命令,如下:perf record java JavaApp另外perf能按出现的百分比降序打印CPU正在执行的函数名以及调用栈,如命令:perf report -n可打印出:这种结果的输出还是不直观的,Linux性能优化大师Brendan Gregg发明了火焰图(因整个图形看起来像燃烧的火焰而得名),以全局的方式来看各个函数的调用时间分布,以图形化的方式列出调用栈。1 初识火焰图火焰图是基于perf的结果生成的图形,我们先了解一下怎么去看火焰图。以下图为例:X轴表示被抽样到的次数。理解X轴的含义,需先了解采样数据的原理。Perf是在指定时间段内,每隔一段时间采集一次数据,被采集到的次数越多,说明该函数的执行总时间长,可能的原因有:调用次数多,或者单次执行时间长。因此,X轴的宽度不能简单的认为是运行时长。Y轴表示调用栈。如何从火焰图看出性能的瓶颈在哪里?最有理由怀疑的地方,顶层的“平顶”。关于perf和火焰图使用方法可以参考官网http://www.brendangregg.com/FlameGraphs/cpuflamegraphs.html。下面是我们利用火焰图来定位问题的一次实战。2 火焰图定位问题的实战2.1 问题场景问题发生的场景是客户端向服务器发起http请求,服务器返回数据给客户端(这是一个非常简单的服务交互)。我们发现使用JDK 8u74的性能要远优于JDK 8u202的性能,下表中统计了20次服务器的响应时长。次数JDK8u74响应时间(单位:秒)JDK8u202响应时间(单位:秒)10.0300.83420.0361.08830.0300.33240.0330.59750.0180.58160.0490.85070.0410.35580.0210.71190.1480.854100.0800.754110.0251.176120.0320.459130.0460.443140.0250.135150.0590.485160.0771.093170.1231.173180.1150.945190.0580.384200.0351.061平均时间0.054050.7155 从响应时间来看,8u202相比8u74性能下降13倍之多,由于应用本身并未做任何修改,所以考虑使用火焰图来定位性能消耗的问题点。在8u74和8u202分别运行应用,并用perf的record抓取数据并生成火焰图。2.2 火焰图定位对比两张火焰图,使用8u74时ClientHandshaker.processMessage占比为1.15%,而在8u202中这个函数占比为23.98%,很明显在ClientHandshaker.processMessage带来了性能差异。 2.3 根因定位两者在这个ClientHandshaker.processMessage上的cpu消耗差异很大,继续分析这个函数找到根因。void processMessage(byte handshakeType, int length) throws IOException { if(this.state >= handshakeType && handshakeType != 0) { //... 异常 } else { label105: switch(handshakeType) { case 0://hello_request this.serverHelloRequest(new HelloRequest(this.input)); break; //... case 2://sever_hello this.serverHello(new ServerHello(this.input, length)); break; case 11:///certificate this.serverCertificate(new CertificateMsg(this.input)); this.serverKey = this.session.getPeerCertificates()[0].getPublicKey(); break; case 12://server_key_exchange 该消息并不是必须的,取决于协商出的key交换算法 //... case 13: //certificate_request 客户端双向验证时需要 //... case 14://server_hello_done this.serverHelloDone(new ServerHelloDone(this.input)); break; case 20://finished this.serverFinished(new Finished(this.protocolVersion, this.input, this.cipherSuite)); } if(this.state < handshakeType) {//握手状态 this.state = handshakeType; } } }processMessage()主要是通过不同的信息类型进行不同的握手消息的处理。而在火焰图中可以看到,JDK8u74图中,主要消耗在函数serverFinished()和serverHello()上,而JDK8u202主要消耗在函数serverHelloDone()和serverKeyExchange()。在介绍火焰图的时候,我们有提到,X轴的长度是映射了被采样到的次数。因此需要进一步确定消耗:函数单次执行耗时过长而成为热点,还是因为频繁调用函数导致函数耗时过长而成为热点。可通过字节码插桩(通过Instrument技术实现对函数的计数,然后编译成agent,执行应用时加载agent,具体使用Instrument的方法可以参考官方文档)查看函数serverHelloDone()的调用次数及执行时间。JDK8u202 数据 Execute count : 253 Execute count : 258 Execute count : 649 Execute count : 661 serverHelloDone execute time [1881195 ns] Execute count : 1223 Execute count : 1234 Execute count : 1843 Execute count : 1852 serverHelloDone execute time [1665012 ns] Execute count : 2446 Execute count : 2456 serverHelloDone execute time [1686206 ns] JDK8u74 数据 Execute count : 56 Execute count : 56 Execute count : 56 Execute count : 56 Execute count : 56 Execute count : 56Execute time是取了每1000次调用的平均值,Execute count每5000ms输出一次总执行次数。很明显使用JDK8u202时在不断调用serverHelloDone,而74在调用56次后没有再调用过这个函数。初始化握手时,serverHelloDone方法中,客户端会根据服务端返回加密套件决定加密方式,构造不同的Client Key Exchange消息;服务器如果允许重用该会话,则通过在Server Hello消息中设置相同的会话ID来应答。这样,客户端和服务器就可以利用原有会话的密钥和加密套件,不必重新协商,也就不再走serverHelloDone方法。从现象来看, JDK8u202没有复用会话,而是建立的新的会话。2.4 水落石出查看JDK8u 161的release notes,添加了TLS会话散列和扩展主密钥扩展支持,找到引入的一个还未修复的issue,对于带有身份验证的TLS的客户端,支持UseExtendedMasterSecret会破坏TLS-Session的恢复,导致不使用现有的TLS-Session,而执行新的Handshake。JDK8u161之后的版本(含JDK8u161),若复用会话时不能成功恢复Session,而是创建新的会话,会造成较大性能消耗,且积压的大量的不可复用的session造成GC压力变大;如果业务场景存在不变更证书密钥,需要复用会话,且对性能有要求,可通过添加参数-Djdk.tls.useExtendedMasterSecret=false来解决这个问题。3 后记如果遇到相关技术问题(包括不限于毕昇JDK),可以通过毕昇JDK社区求助。毕昇JDK社区每双周周二举行技术例会,同时有一个技术交流群讨论GCC、LLVM和JDK等相关编译技术,感兴趣的同学可以添加如下微信小助手入群本文转载自 openEuler-使用 perf 解决 JDK8 小版本升级后性能下降的问题
-
rmic功能说明: rmic 为远程对象生成 stub 和 skeleton。 语法: rmic [ options ] package-qualified-class-name(s)补充说明: rmic 编译器根据编译后的 Java 类(含有远程对象实现)名,为远程对象生成 stub 和 skeleton(远程对象是指实现 java.rmi.Remote 接口的对象)。在 rmic 命令中所给的类必须是经 javac 命令成功编译且是完全包限定的类。 命令选项 -classpath[路径] 指定 rmic 用于查询类的路径。如果设置了该选项,它将覆盖缺省值或 CLASSPATH 环境变量。目录用冒号分隔。 -d[目录] 指定类层次的根目录。此选项可用来指定 stub 和 skeleton 文件的目标目录。 -depend 使编译器考虑重新编译从其它类引用的类。 一般来说,它只重新编译从源代码引用的遗漏或过期的类。 -g 允许生成调试表格。调试表格含有行号和局部变量的有关信息,即 Java 调试工具所使用的信息。缺省情况下,只生成行号。 -J 与 -D 选项联用,它将紧跟其后的选项( -J 与 -D 之间无空格)传给 java 解释器。 -keepgenerated 为 stub 和 skeleton 文件保留所生成的 .java 源文件,并将这些源文件写到与 .class 文件相同的目录中,如果要指定目录,则使用 -d 选项。 -nowarn 关闭警告。如果使用该选项,则编译器不输出任何警告信息。 -show 显示 rmic 编译器的 GUI(图形用户界面)。输入一个或多个包限定类名(以空格分隔),并按回车键或“显示”按钮,创建 stub 和 skeleton。 -vcompat (缺省值)创建与 JDK 1.1 和 1.2 stub 协议版本都兼容的 stub 和 skeleton。 -verbose 使编译器和链接器输出关于正在编译哪些类和正在加载哪些类文件的信息。 -v1.1 创建 JDK 1.1 stub 协议版本的 stub 和 skeleton。 -v1.2 只创建 JDK 1.2 stub 协议版本的 stub。rmid功能说明: rmid 启动激活系统守护进程,以便能够在 Java 虚拟机上注册和激活对象。语法: rmid [-port port] [-log dir]补充说明: rmid 工具启动激活系统守护进程。必须先启动激活系统守护进程,才能向激活系统注册可被激活的对象或在 Java 虚拟机上激活可被激活的对象。命令选项 -C<某些命令行选项> 指定一个选项,在创建每个 rmid 的子守护进程(激活组)时,该选项以命令行参数的形式传给该子守护进程。 -log[目录] 指定目录的名称,激活系统守护进程在该目录中写入其数据库及相关信息。缺省状态下,将在执行 rmid 命令的目录中创建一个 log 目录。 -port[端口] 指定 rmid 的注册服务程序所使用的端口。激活系统守护进程将 ActivationSystem 与该注册服务程序中的名称java.rmi.activation.ActivationSystem 捆绑在一起。 -stop 停止 -port 选项所指定端口上的当前 rmid 调用。若未指定端口,则将停止在端口 1098 上运行的 rmid。rmiregistry功能说明: rmiregistry 命令可在当前主机的指定端口上启动远程对象注册服务程序。语法: rmiregistry [port]补充说明: rmiregistry 命令在当前主机的指定 port 上创建并启动远程对象注册服务程序。如果省略 port,则注册服务程序将在 1099 端口上启动。rmiregistry 命令不产生任何输出而且一般在后台运行。远程对象注册服务程序是自举命名服务。主机上的 RMI 服务器将利用它将远程对象绑定到名字上。客户机即可查询远程对象并进行远程方法调用。注册服务程序一般用于定位应用程序需调用其方法的第一个远程对象。该对象反过来对各应用程序提供相应的支持,用于查找其它对象。
-
官网下载Jmeterhttp://jmeter.apache.org/下载最新版本的 JMeter,解压文件到任意目录 安装JDK,配置Java环境就直接看着篇博客就好啦:https://www.cnblogs.com/poloyy/p/12744072.html注意:应该避免JDK安装路径,Jmeter路径有中文和空格 配置Jmeter环境变量 检查Jmeter配置是否成功cmd敲jmeter或者win+r敲jmeter,能打开jmeter就安装配置成功了 上述只敲jmeter的话,cmd命令窗口会一直存在,很不友好
-
调优工具忘记密码怎么办? 解决方式:重装重新设置密码卸载:cd /opt/hyper_tuner/ 执行命令:./hyper_tuner_uninstall.sh -a注意:/opt是默认的安装目录, 如果用户安装的时候自己制定了目录,替换成自己的命令安装 java 调优工具进入安装包解压目录 cd /home/Hyper_tuner/Hyper_tuner/ 执行命令:./hyper_tuner_install.sh -j -ip=255.255.255.255 -jip=255.255.255.255注意:1、/home 需要替换成用户自己的解压目录2、255.255.255.255 需要替换成自己服务器的ip3、如果系统默认的jdk环境不是 11,则需要额外提供 jdk11 的目录,提供 jh 设置。如:./hyper_tuner_install.sh -j -jh=/root/jdk11 -ip=255.255.255.255 -jip=255.255.255.255可以通过 java -verfsion 命令查看 jdk 版本等工具安装成功后,浏览器重新登录,就可以重新设置管理员密码
-
问题分析查看异常重启的regionserver的hbase.out(/var/log/Bigdata/hbase/rs/hbase-omm-regionserver-xxx.out)日志显示重启原因为jvm crash。查看对应hs_err_pid.log所有显示异常时堆栈再0x43。GC参数配置xmx 41G,表压缩算法ZSTD,两个条件共存时会导致RegionServer重启异常,其中一个不满足,不会触发该问题。问题解决参考 修改GC配置在31G以下或者将表的压缩算法改成其他的。
-
请问毕昇JDK8现在是否可以用于非ARM的LINUX生产环境?稳定性及性能相比adoptOpenjdk如何呢?配合kettle、tomcat等主流开源软件使用是否会有问题呢?感谢各位
-
AR502H的容器是开放的,并且制作容器的脚本已经发布了,请参考《软件二次开发指南》中相关章节那么如何在这个脚本中修改,制作带有JDK的容器内,可参考以下步骤:第一步:在build目录下创建一个jdk目录,里面存放下载好的jdk文件,以下已OpenJDK为例第二步:修改编译环境中的/usr/local/bin/create-rootfs的脚本,新增3处内容,如下图红框内的部分第三步:参考边缘计算网关二次开发指南中的LXC容器包制作章节,制作LXC的ova镜像最后,在设备上安装容器,登录到容器内,查看java版本号注:如何把java程序制作成应用,后续会发布出来,调测阶段,可以先使用java -jar拉起对应的程序试试效果。如在使用过程中有问题请跟帖讨论。原创文章,转载请注明出处
-
环境: JAVA 14esdk-obs-java [3.19.7,)问题:最近使用时一直出现408
-
现在默认是1.8,我们的项目已经用高版本的jdk了,可以自己安装jdk吗?
-
#化鲲为鹏,我有话说# > 题外话:很高兴能够申请成功鲲鹏的公测,收到消息,第一时间申请了鲲鹏服务器,打算好好利用这段时间对鲲鹏服务器在企业应用可用性上进行测试,毕竟ARM和X86还是有很大差别的,很多企业级应用能否在鲲鹏上稳定运行,是否能够保证性能,是否可以适应技术架构及其中间件环境,是选择鲲鹏的一个重要的考量。本次我就先对java及其相关环境进行测试。这是我的第一帖,后续我还会持续对鲲鹏的测试反馈发帖交流。 首先,对于鲲鹏[官网介绍](https://www.huaweicloud.com/kunpeng/software/openjdk.html)其是支持OpenJDK环境的,但是在企业中,很少直接使用OpenJDK,而是使用oracle官方版本更多一些。那我就先在鲲鹏服务中先搭建jdk环境,本次测试使用的jdk8,分别安装OpenJDK和Oracle官方jdk环境。 ## 0. 试验环境 服务器规格: 鲲鹏通用计算增强型 | kc1.15xlarge.2 操作系统 : Ubuntu 18.04 64bit with ARM ## 1.OpenJDK 服务器初始系统中已经安装了OpenJDK,安装版本如下: ```bash openjdk version "1.8.0_212" OpenJDK Runtime Environment (build 1.8.0_212-8u212-b03-0ubuntu1.18.04.1-b03) OpenJDK 64-Bit Server VM (build 25.212-b03, mixed mode) ``` 如果你使用其他系统,可以参考[鲲鹏官方的安装说明](https://www.huaweicloud.com/kunpeng/software/openjdk.html) ## 2. Oracle官方版本 - 首先需要卸载鲲鹏上自带的openjdk ```bash apt-get autoremove openjdk-8-jdk ``` - 然后下载oracle官方jdk,这里时[下载地址](https://www.oracle.com/technetwork/java/javase/downloads/java-archive-javase8u211-later-5573849.html),这里需要注意,一定要下载RAM版本的jdk,否则无法运行。 - 加压并安装jdk ```bash tar -vzxf jdk-8u212-linux-arm64-vfp-hflt.tar.gz mv jdk1.8.0_212/ jdk vi /etc/profile # 在文件最后加上下面内容 export JAVA_HOME=/opt/jdk export PATH=$PATH:$JAVA_HOME/bin ``` - 验证是否安装成功 ```bash java -version # 看到以下内容说明已经安装完成 java version "1.8.0_212" Java(TM) SE Runtime Environment (build 1.8.0_212-b10) Java HotSpot(TM) 64-Bit Server VM (build 25.212-b10, mixed mode) ``` ## 3.总结 可以看到,基于鲲鹏的JAVA环境安装过程和基于X86的安装过程并没有什么区别,而且无论从开源社区还是oracke官方都是支持ARM框架的JAVA环境。而JAVA是基于跨平台的,只要能够正常运行JAVA环境,那么基于JAVA的企业级应用,都可以很容易的迁移到麒麟服务器上。
-
有时候老版本软件的移植依赖 这个 jrub-complete-1.6.8 源码在:https://github.com/jruby/jruby/releases/tag/1.6.8尝试编译,貌似JDK8移除了apt,编译报错:[INFO] BUILD FAILED[INFO] /build/01_maven_project/jruby/jruby-1.6.8/build.xml:680: The following error occurred while executing this line:[INFO] /build/01_maven_project/jruby/jruby-1.6.8/build.xml:264: Problem: failed to create task or type apt[INFO] Cause: The name is undefined.[INFO] Action: Check the spelling.[INFO] Action: Check that any custom tasks/types have been declared.[INFO] Action: Check that any <presetdef>/<macrodef> declarations have taken place.用JDK1.7,也报错:[INFO] BUILD FAILED[INFO] /build/01_maven_project/jruby/jruby-1.6.8/build.xml:681: The following error occurred while executing this line:[INFO] /build/01_maven_project/jruby/jruby-1.6.8/build.xml:282: The following error occurred while executing this line:[INFO] /build/01_maven_project/jruby/jruby-1.6.8/build.xml:287: Java returned: 1[INFO][INFO] Total time: 17 seconds[INFO] ------------------------------------------------------------------------[INFO] BUILD FAILURE-X:[INFO] BUILD FAILED[INFO] /build/01_maven_project/jruby/jruby-1.6.8/build.xml:681: The following error occurred while executing this line:[INFO] /build/01_maven_project/jruby/jruby-1.6.8/build.xml:282: The following error occurred while executing this line:[INFO] /build/01_maven_project/jruby/jruby-1.6.8/build.xml:287: Java returned: 1[INFO][INFO] Total time: 16 seconds[INFO] ------------------------------------------------------------------------[INFO] Reactor Summary:[INFO][INFO] JRuby Shared 1.6.8 ................................. SUCCESS [ 3.443 s][INFO] JRuby Common ....................................... SUCCESS [ 0.061 s][INFO] JRuby .............................................. FAILURE [ 18.315 s][INFO] JRuby Core ......................................... SKIPPED[INFO] JRuby Complete ..................................... SKIPPED[INFO] JRuby Stdlib ....................................... SKIPPED[INFO] JRuby Distribution ................................. SKIPPED[INFO] JRuby Rake Plugin .................................. SKIPPED[INFO] docs ............................................... SKIPPED[INFO] JRuby Manual pages 1.6.8 ........................... SKIPPED[INFO] ------------------------------------------------------------------------[INFO] BUILD FAILURE[INFO] ------------------------------------------------------------------------[INFO] Total time: 22.313 s[INFO] Finished at: 2019-07-30T11:07:45+08:00[INFO] ------------------------------------------------------------------------[ERROR] Failed to execute goal org.codehaus.mojo:exec-maven-plugin:1.1:exec (default) on project jruby: Result of /bin/sh -c cd /build/01_maven_project/jruby/jruby-1.6.8/maven/jruby/../.. && ant jar-dist execution is: '1'. -> [Help 1]org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.codehaus.mojo:exec-maven-plugin:1.1:exec (default) on project jruby: Result of /bin/sh -c cd /build/01_maven_project/jruby/jruby-1.6.8/maven/jruby/../.. && ant jar-dist execution is: '1'. at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:213) at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:154) at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:146) at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117) at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81) at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56) at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128) at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305) at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192) at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105) at org.apache.maven.cli.MavenCli.execute (MavenCli.java:954) at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:288) at org.apache.maven.cli.MavenCli.main (MavenCli.java:192) at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke (Method.java:606) at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:289) at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:229) at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:415) at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:356)Caused by: org.apache.maven.plugin.MojoExecutionException: Result of /bin/sh -c cd /build/01_maven_project/jruby/jruby-1.6.8/maven/jruby/../.. && ant jar-dist execution is: '1'. at org.codehaus.mojo.exec.ExecMojo.execute (ExecMojo.java:260) at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:137) at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:208) at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:154) at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:146) at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117) at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81) at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56) at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128) at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305) at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192) at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105) at org.apache.maven.cli.MavenCli.execute (MavenCli.java:954) at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:288) at org.apache.maven.cli.MavenCli.main (MavenCli.java:192) at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke (Method.java:606) at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:289) at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:229) at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:415) at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:356)[ERROR][ERROR][ERROR] For more information about the errors and possible solutions, please read the following articles:[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException[ERROR][ERROR] After correcting the problems, you can resume the build with the command[ERROR] mvn <goals> -rf :jruby
-
1、简介 JDK是 Java 语言的软件开发工具包,主要用于移动设备、嵌入式设备上的java应用程序。JDK是整个java开发的核心,它包含了JAVA的运行环境(JVM+Java系统类库)和JAVA工具。官方链接:https://www.oracle.com/technetwork/java/javase/downloads/index.html 类别:工具包2、基础环境类别子项版本获取地址(方法)华为云虚拟机RC3(916)--OSCentOS7.5Kernel4.14软件包Jdk1.8.03、依赖安装无4、组件编译安装此步骤建议在chroot环境下进行,一来对chroot环境可以随意修改,不会影响系统,二来多人共用系统环境,免不了对系统有更改,chroot环境更纯净。1)创建chroot环境,执行后/root/zmm目录下就是个可用的chroot环境,chroot进去即可进行任意操作。yum install --installroot=/root/leiju/ -y basesystem yum rpm-buildmount --bind /dev/ /root/leiju/devmount --bind /proc/ /root/leiju/proc/Chroot环境创建后,进去发现很多基础命令没有,比如vi,需要自行安装对应的rpm包。如下图所示:已可用。其它命令如遇到不可用的,请参考上图的方法添加。2)配置YUM源推荐所有reo源修改为华为开源镜像站,速度更快更稳定。配置参考如下图所示: bash-4.2# grep "huawei" -ri /etc/yum.repos.d//etc/yum.repos.d/CentOS-EPEL.repo:baseurl=https://mirrors.huaweicloud.com/epel/7/aarch64//etc/yum.repos.d/euleros.repo:baseurl=http://mirrors.huaweicloud.com/euler/2.3/os/aarch64//etc/yum.repos.d/euleros.repo:gpgkey=http://mirrors.huaweicloud.com/euler/2.3/os/RPM-GPG-KEY-EulerOS/etc/yum.repos.d/CentOS-Base.repo:baseurl=https://mirrors.huaweicloud.com/centos-altarch/7/os/aarch64//etc/yum.repos.d/CentOS-Base.repo:baseurl=https://mirrors.huaweicloud.com/centos-altarch/7/updates/aarch64//etc/yum.repos.d/CentOS-Base.repo:baseurl=https://mirrors.huaweicloud.com/centos-altarch/7/extras/aarch64//etc/yum.repos.d/CentOS-Base.repo:baseurl=https://mirrors.huaweicloud.com/centos-altarch/7/centosplus/aarch64/3)jdk安装新建并进入存放jdk下载目录mkdir -p /leiju/jdkcd /leiju/jdk下载解压jdk压缩包wget https://download.oracle.com/otn/java/jdk/8u212-b10/59066701cf1a433da9770636fbc4c9aa/jdk-8u212-linux-arm64-vfp-hflt.tar.gz?AuthParam=1561876866_2f2d87400ee6df63d14b9eae0d244553tar zxvf jdk-8u212-linux-arm64-vfp-hflt.tar.gz\?AuthParam\=1561876866_2f2d87400ee6df63d14b9eae0d244553将解压后的jdk目录移到/usr/local/目录下mv jdk1.8.0_212 /usr/local/5、系统配置修改配置文件/etc/profile,在文件最后添加下列配置vi /etc/profile使配置文件立即生效source /etc/profile6、测试测试内容:查看jdk是否安装成功java -version测试结果:安装成功7、参考信息官方参考文档:https://www.oracle.com/technetwork/java/javase/documentation/index.html 8、FQAQ:jdk下载时可能会下载不了?A:需要自己申请个oracle账号,即可正常下载。
推荐直播
-
华为云码道-玩转OpenClaw,在线养虾2026/03/11 周三 19:00-21:00
刘昱,华为云高级工程师/谈心,华为云技术专家/李海仑,上海圭卓智能科技有限公司CEO
OpenClaw 火爆开发者圈,华为云码道最新推出 Skill ——开发者只需输入一句口令,即可部署一个功能完整的「小龙虾」智能体。直播带你玩转华为云码道,玩转OpenClaw
回顾中 -
华为云码道-AI时代应用开发利器2026/03/18 周三 19:00-20:00
童得力,华为云开发者生态运营总监/姚圣伟,华为云HCDE开发者专家
本次直播由华为专家带你实战应用开发,看华为云码道(CodeArts)代码智能体如何在AI时代让你的创意应用快速落地。更有华为云HCDE开发者专家带你用码道玩转JiuwenClaw,让小艺成为你的AI助理。
回顾中 -
Skill 构建 × 智能创作:基于华为云码道的 AI 内容生产提效方案2026/03/25 周三 19:00-20:00
余伟,华为云软件研发工程师/万邵业(万少),华为云HCDE开发者专家
本次直播带来两大实战:华为云码道 Skill-Creator 手把手搭建专属知识库 Skill;如何用码道提效 OpenClaw 小说文本,打造从大纲到成稿的 AI 原创小说全链路。技术干货 + OPC创作思路,一次讲透!
回顾中
热门标签