• [交流吐槽] 用java写Student类的功能
    1)编写一个Java程序片断,以定义一个表示学生的类Student。这个类的属性有“学号”、“班号”、“姓名”、“性别”、“年龄”,方法有“获得学号”、“获得班号”、“获得性别”、“获得姓名”、“获得年龄”。2)为类Student增加一个方法public String toString( ),该方法把Student类的对象的所有属性信息组合成一个字符串以便输出显示。编写一个Java Application程序,创建Student类的对象,并验证新增加的功能。 package xin;import java.util.Scanner;public class Student {    int number;    String classnumber;    int age;    String name;    String sex;       Student(int x,String y,int z,String p){     number = x;     classnumber = y;     age = z;     name = p;    }     int getNumber() {     return number;  //返回学号    }     String getSClassnumber() {     return classnumber;  //返回班号    }     int getAge() {     return age;     //返回年龄    }     String getName() {      return name;    //返回姓名     }     String getSex() {      return sex;   //返回性别     }    public String toString() {      return "学号:"+number+" 班号:"+classnumber+" 姓名:"+name+" 性别:"+sex+" 年龄:"+age;    }   public static void main(String args[]) {   boolean boo,a;   int number1,age1;   String classnumber1,st;   String name1,sex1;   Student stu = new Student(1,"s",1,"xaio");   Scanner reader = new Scanner(System.in);   System.out.println("请输入学号、班号、姓名、性别、年龄:");   stu.number = reader.nextInt();   stu.classnumber = reader.next();   stu.name = reader.next();   stu.sex = reader.next();   stu.age = reader.nextInt();   st = stu.toString();   System.out.println(st);   System.out.println("是否修改该学生信息?");   System.out.println("如果修改则输入true,反之false");    a = reader.nextBoolean();    if(a) {   System.out.println("请输入学号、班号、姓名、性别、年龄:");   number1 = reader.nextInt();   classnumber1 = reader.next();   name1 = reader.next();   sex1 = reader.next();   age1 = reader.nextInt();       System.out.println("学号:"+number1+" 班号:"+classnumber1+     " 姓名:"+name1+" 性别:"+sex1+" 年龄:"+age1);   }   else   {System.out.println("继续执行下一步");}      System.out.println("输入true继续,false退出");        boo = reader.nextBoolean();     System.out.println("*********************");      if(boo) {       main(args);   //函数调用      }      else       System.out.println("程序无法执行!!!!");   }}
  • [互动交流] FusionInsight安全模式ES使用java-transport-client认证问题
    springboot 使用 java-transport-client 读写 FusionInsight HD 6.5.1 安全模式 ES 6.7.1 ,刚启动服务时可以正常读写 ES ,但过一段时间后就报错,错误堆栈如下认证代码复制于样例已替换下面三个包,请问是否替换正确elasticsearch-transport-clientelasticsearchtransport
  • [酷哥说库] 2021年编程语言名单:SQL位居榜首,Java、Python紧随其后
    不同的编程语言会对我们的求职产生相当大的影响,但是目前哪种编程语言最受公司欢迎呢?Emsi Burning Glass收集并分析了数百万个招聘信息,以下是出现得最多的编程语言:图来源于Emsi Burning Glass如图所示, SQL 位居榜首,可见各大公司在招聘时往往倾向于能够熟练使用SQL的技术人员。比起Python、Java 和JavaScript等编程语言,SQL并非使用最广泛的语言。但是,之所以各大公司要求精通SQL,原因在于它能够用于管理和查询关系数据库,是数据操作的基础。Java位列第二位。最近推出的Java 17在性能上大幅度提高,同时稳定性和安全性也在不断升级。该语言为众多软件后端提供支持,其中包括Android应用程序和大数据分析等等。Burning Glass表示,这也是Java 开发人员工资较高的关键原因之一。第三名编程语言为Python。Python一直是一种非常流行的编程语言,如今逐步用于数据科学、机器学习和其他高度专业化的领域。开发者调查分析公司 SlashData表示,Python的全球开发者社区人数大约有1130万,并且仍在持续增长。文章来源:https://blog.csdn.net/csdndevelopers/article/details/122316758
  • [热门活动] 最新编程语言排行榜出炉!华为专家邀你一起学编程!
    新年将至,正是重新再出发的好时候。如果要学一门新的编程语言,该从哪个开始入手呢?不如来看下编程语言风向标:2021年最佳编程语言排行榜!近日,IEEE Spectrum发布的2021年度编程语言排行榜,与2020年排行榜相比,Python、Java、C、C++ 和JavaScript 依然占据 2021 排行榜的前 5 名。而在TIOBE编程语言社区发布的12月编程语言排行榜中,Python、C、Java、C++、C#也名列排行榜前5名,都展示出非常火热的发展势头。*图片来源于IEEE Spectrum、TIOBE编程语言没有好坏之分,重点在于应用。各技术社区编程语言排行榜,是编程语言流行趋势的一个指标,可以帮助程序员更好的了解自己所学的编程语言在市场中的竞争力。对于新入门及需要掌握多门编程语言的程序员来说,了解当下编程语言的热门程度是非常有必要的。免费精品课程推荐接下来给大家介绍一下排行前列且较稳定,最值得程序员学习的几个开发语言,同时给大家推荐一些适合自学的免费精品课程。稳居榜首的PythonPython是时下最为流行的编程语言之一,在诸多领域都有着广泛的应用;其优雅的语法、简单的规则让程序员在更短的时间内实现更多的功能。众所周知的JavaJava是目前使用最为广泛的网络编程语言之一,具有易学好用的特点,基于对象的编程更符合人的思维模式,使人们更容易编写程序;与平台无关是 Java 语言最大的优势。经久不衰的C语言当今主流编程语言中,C语言的历史最为悠远且经久不衰,在程序语言发展史上具有重要地位。C语言偏向于底层硬件交互,多用于系统软件开发,设备驱动开发以及嵌入式开发。其中著名的UNIX操作系统就是由C语言所开发。主导性非常强的C++C++是一门被广泛使用的现代编程语言,在兼顾性能和灵活的原则下拥有大量特性,它非常灵活,功能也非常强大,是可以在保证功能的前提下性能最高的语言之一。因互联网而生的JavaScriptJavaScript是一种在网络浏览器上运行的变成语言,这种语言我们称之为脚本语言。它因互联网而生,紧跟浏览器的发展而发展。开发语言大讲堂华为云培训中心官方推出Python,Java,C,C++,Rust,JavaScript等免费精品课程。非常适合打算自学编程语言,或者仅有部分闲暇时间学习编程语言的学员。由华为云专家精心打造课程配合“课程+测评+实战+认证”四步帮助你0基础从入门到精通通过自主“学测练考”不仅能让你对开发语言有整体概念还可以帮助你培养编程思维!此外,通过学习,还可获取华为云官方认证证书,赢取富士INSTAX 一次成像相机、京东3D颈肩按 摩披肩、无线榨汁机、充电宝、帆布包、无线鼠标等1000+好礼!扫描下方二维码了解详情活动日期:即日起截至3月27日课程免费、实验免费奖品有限,发完即止还等什么,马上占位吧!
  • [二次开发] 【MRS】【YARN java api】调用yarnclient的接口提交应用到RM的java样例demo
    【功能模块】【操作步骤&问题现象】1、能否提供一个调用yarnclient的接口提交应用到RM的java样例demo,感谢【截图信息】【日志信息】(可选,上传日志内容或者附件)
  • [问题求助] 【openGauss】java用jdbc连openGauss,出现报错
    java用jdbc连openGauss,出现报错:Unsupported major.minor version 52.0 (无法载入的.类 [org.postgresql.Driver])是什么原因?环境:java jdk是1.7 Tomcat用的8.x版本
  • [交流吐槽] 免费学习Java编程
    https://education.huaweicloud.com/programs/1ecdf4b3-15db-4ca4-b1b9-8026effafc4c/about   
  • [问题求助] 如何学习java后台开发
    如何学习java后台开发,有学习路线吗
  • [交流吐槽] 日常Java练习题2
    区分类中重载方法的依据是( )。正确答案: C 你的答案: C (正确)不同的形参名称不同的返回值类型不同的形参列表不同的访问权限题解:两个重载函数必须在下列一个或两个方面有所区别:1、函数的参数个数不同。2、函数的参数类型不同或者参数类型顺序不同
  • [交流吐槽] 日常Java练习题1
    设Tree为已定义的类名,下列语句能正确创建 Tree 对象的是 。正确答案: B 你的答案: B (正确)Tree t=new Tree;Tree t=new Tree();Tree t=Tree();Tree t[ ]=new Tree[10];题解:需要对象,当然只需new一个了,还有别忘了括号。
  • [Java] Java的编译工具
    Eclipse:一个开放源代码的、基于Java的可扩展开发平台 。NetBeans:开放源码的Java集成开发环境,适用于各种客户机和Web应用。IntelliJ IDEA:在代码自动提示、代码分析等方面的具有很好的功能。 MyEclipse:由Genuitec公司开发的一款商业化软件,是应用比较广泛的Java应用程序集成开发环境   。EditPlus:如果正确配置Java的编译器“Javac”以及解释器“Java”后,可直接使用EditPlus编译执行Java程序 。
  • [java] Java编程中忽略这些细节,Bug肯定找上你
    >摘要:在Java语言的日常编程中,也存在着容易被忽略的细节,这些细节可能会导致程序出现各种Bug。本文分享自华为云社区[《Java编程中容易忽略的细节总结丨【奔跑吧!JAVA】》](https://bbs.huaweicloud.com/blogs/273066?utm_source=csdn&utm_medium=bbs-ex&utm_campaign=other&utm_content=content),作者:jackwangcumt 。 Java语言构建的各类应用程序,在人类的日常生活中占用非常重要的地位,各大IT厂商几乎都会使用它来构建自己的产品,为客户提供服务。作为一个企业级应用开发语言,稳定和高效的运行,至关重要。在Java语言的日常编程中,也存在着容易被忽略的细节,这些细节可能会导致程序出现各种Bug,下面就对这些细节进行一些总结: # 1 相等判断中的==和equals 在很多场景中,我们都需要判断两个对象是否相等,一般来说,判定两个对象的是否相等,都是依据其值是否相等,如两个字符串a和b的值都为"java",则我们认为二者相等。在Java中,有两个操作可以判断是否相当,即==和equals,但二者是有区别的,不可混用。下面给出示例: String a = "java"; String b = new String("java"); System.out.println(a == b);//false System.out.println(a.equals(b));//true 字符串a和b的字面值都为"java",用a == b判断则输出false,即不相等,而a.equals(b)则输出true,即相等。这是为什么呢?在Java中,String是一个不可变的类型,一般来说,如果两个String的值相等,默认情况下,会指定同一个内存地址,但这里字符串String b用new String方法强制生成一个新的String对象,因此,二者内存地址不一致。由于 == 需要判断对象的内存地址是否一致,因此返回false,而equals默认(override后可能不一定)是根据字面值来判断,即相等。 下面再给出一个示例: //integer -128 to 127 Integer i1 = 100; Integer i2 = 100; System.out.println(i1 == i2);//true i1 = 300; i2 = 300; System.out.println(i1 == i2);//false System.out.println(i1.equals(i2));//true 这是由于Java中的Integer数值的范围为-128到127,因此在这范围内的对象的内存地址是一致的,而超过这个范围的数值对象的内存地址是不一致的,因此300这个数值在 == 比较下,返回false,但在equals比较下返回true。 # 2 switch语句中丢失了break 在很多场景中,我们需要根据输入参数的范围来分别进行处理,这里除了可以使用if ... else ...语句外,还可以使用switch语句。在switch语句中,会罗列出多个分支条件,并进行分别处理,但如果稍有不注意,就可能丢失关键字break语句,从而出现预期外的值。下面给出示例: //缺少break关键字 public static void switchBugs(int v ) { switch (v) { case 0: System.out.println("0"); //break case 1: System.out.println("1"); break; case 2: System.out.println("2"); break; default: System.out.println("other"); } } 如果我们使用如下语句进行调用: `switchBugs(0);` 则我们预期返回"0",但是却返回"0" "1"。这是由于case 0 分支下缺少break关键字,则虽然程序匹配了此分支,但是却能穿透到下一个分支,即case 1分支,然后遇到break后返回值。 # 3 大量的垃圾回收,效率低下 字符串的拼接操作,是非常高频的操作,但是如果涉及的拼接量很大,则如果直接用 + 符号进行字符串拼接,则效率非常低下,程序运行的速度很慢。下面给出示例: private static void stringWhile(){ //获取开始时间 long start = System.currentTimeMillis(); String strV = ""; for (int i = 0; i 100000; i++) { strV = strV + "$"; } //strings are immutable. So, on each iteration a new string is created. // To address this we should use a mutable StringBuilder: System.out.println(strV.length()); long end = System.currentTimeMillis(); //获取结束时间 System.out.println("程序运行时间: "+(end-start)+"ms"); start = System.currentTimeMillis(); StringBuilder sb = new StringBuilder(); for (int i = 0; i 100000; i++) { sb.append("$"); } System.out.println(strV.length()); end = System.currentTimeMillis(); System.out.println("程序运行时间: "+(end-start)+"ms"); } 上述示例分别在循环体中用 + 和 StringBuilder进行字符串拼接,并统计了运行的时间(毫秒),下面给出模拟电脑上的运行结果: //+ 操作 100000 程序运行时间: 6078ms StringBuilder操作 100000 程序运行时间: 2ms 由此可见,使用StringBuilder构建字符串速度相比于 + 拼接,效率上高出太多。究其原因,就是因为Java语言中的字符串类型是不可变的,因此 + 操作后会创建一个新的字符串,这样会涉及到大量的对象创建工作,也涉及到垃圾回收机制的介入,因此非常耗时。 # 4 循环时删除元素 有些情况下,我们需要从一个集合对象中删除掉特定的元素,如从一个编程语言列表中删除java语言,则就会涉及到此种场景,但是如果处理不当,则会抛出ConcurrentModificationException异常。下面给出示例: private static void removeList() { List lists = new ArrayList(); lists.add("java"); lists.add("csharp"); lists.add("fsharp"); for (String item : lists) { if (item.contains("java")) { lists.remove(item); } } } 运行上述方法,会抛出错误,此时可以用如下方法进行解决,即用迭代器iterator,具体如下所示: private static void removeListOk() { List lists = new ArrayList(); lists.add("java"); lists.add("csharp"); lists.add("fsharp"); Iterator hatIterator = lists.iterator(); while (hatIterator.hasNext()) { String item = hatIterator.next(); if (item.contains("java")) { hatIterator.remove(); } } System.out.println(lists);//[csharp, fsharp] } # 5 null引用 在方法中,首先应该对参数的合法性进行验证,第一需要验证参数是否为null,然后再判断参数是否是预期范围的值。如果不首先进行null判断,直接进行参数的比较或者方法的调用,则可能出现null引用的异常。下面给出示例: private static void nullref(String words) { //NullPointerException if (words.equals("java")){ System.out.println("java"); }else{ System.out.println("not java"); } } 如果此时我们用如下方法进行调用,则抛出异常: `nullref(null)` 这是由于假设了words不为null,则可以调用String对象的equals方法。下面可以稍微进行一些修改,如下所示: private static void nullref2(String words) { if ("java".equals(words)){ System.out.println("java"); }else{ System.out.println("not java"); } } 则此时执行则可以正确运行: nullref2(null) # 6 hashCode对equals的影响 前面提到,equals方法可以从字面值上来判断两个对象是否相等。一般来说,如果两个对象相等,则其hash code相等,但是如果hash code相等,则两个对象可能相等,也可能不相等。这是由于Object的equals方法和hashCode方法可以被Override。下面给出示例: package com.jyd; import java.util.Objects; public class MySchool { private String name; MySchool(String name) { this.name = name; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } MySchool _obj = (MySchool) o; return Objects.equals(name, _obj.name); } @Override public int hashCode() { int code = this.name.hashCode(); System.out.println(code); //return code; //true //随机数 return (int) (Math.random() * 1000);//false } } Set mysets = new HashSet(); mysets.add(new MySchool("CUMT")); MySchool obj = new MySchool("CUMT"); System.out.println(mysets.contains(obj)); 执行上述代码,由于hashCode方法被Override,每次返回随机的hash Code值,则意味着两个对象的hash code不一致,那么equals判断则返回false,虽然二者的字面值都为"CUMT"。 # 7 内存泄漏 我们知道,计算机的内存是有限的,如果Java创建的对象一直不能进行释放,则新创建的对象会不断占用剩余的内存空间,最终导致内存空间不足,抛出内存溢出的异常。内存异常基本的单元测试不容易发现,往往都是上线运行一定时间后才发现的。下面给出示例: package com.jyd; import java.util.Properties; //内存泄漏模拟 public class MemoryLeakDemo { public final String key; public MemoryLeakDemo(String key) { this.key =key; } public static void main(String args[]) { try { Properties properties = System.getProperties(); for(;;) { properties.put(new MemoryLeakDemo("key"), "value"); } } catch(Exception e) { e.printStackTrace(); } } /* @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; MemoryLeakDemo that = (MemoryLeakDemo) o; return Objects.equals(key, that.key); } @Override public int hashCode() { return Objects.hash(key); } */ } 此示例中,有一个for无限循环,它会一直创建一个对象,并添加到properties容器中,如果MemoryLeakDemo类未给出自己的equals方法和hashCode方法,那么这个对象会被一直添加到properties容器中,最终内存泄漏。但是如果定义了自己的equals方法和hashCode方法(被注释的部分),那么新创建的MemoryLeakDemo实例,由于key值一致,则判定为已存在,则不会重复添加,此时则不会出现内存溢出。
  • [问题求助] Tuning Kit,java性能分析添加目标环境失败
  • [方案分享] ModelArts 在线服务API对接demo-java版本
    # 1. 服务说明 ModelArts在线服务:将训练好的模型通过modelarts在线服务平台部署为一个Web Service服务。对外提供一个标准的Restful API,可使用HTTPS协议访问。 # 2. Api对接前置说明 ## 2.1 确认服务正常 ### 2.1.1 确认服务运行状态 Ⅰ. 在华为云控制台查看已部署的在线服务,确认状态为运行中。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202111/23/185859gzar2aitfez2ommw.png) Ⅱ. 进入已运行的在线服务,进入预测功能,进行接口调用。 a.上传图片 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202111/23/185917bas9rulxltospkpk.png) b.图片预测 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202111/23/185926uhslqcnczf94hbmt.png) ### 2.1.2 获取token Ⅰ. 请求接口方式:https://support.huaweicloud.com/api-iam/iam_30_0001.html 集成华为SDK:https://sdkcenter.developer.huaweicloud.com/?product=%E7%BB%9F%E4%B8%80%E8%BA%AB%E4%BB%BD%E8%AE%A4%E8%AF%81%E6%9C%8D%E5%8A%A1&language=java Ⅱ 调试过程,可以使用API Explorer 调用统一身份认证服务 KeystoneCreateUserTokenByPassword接口获取IAM用户token: https://apiexplorer.developer.huaweicloud.com/apiexplorer/doc?product=IAM&api=KeystoneCreateUserTokenByPassword # 3. Demo适用服务说明 该服务调用demo适用于Java语言,调用华为云mdoelarts在线服务、APIG等涉及到图片上传的以及返接口返回信息为json串的接口。 # 4. Demo代码 import javax.net.ssl.HttpsURLConnection; import java.io.*; import java.net.URL; /** ** 向华为云上传图片的demo **/ public class UploadImageDemo { public static void main(String[] args) { // 服务器url String modelApi = "https://XXX"; // token String tokenStr = "XXXX"; // 图片的绝对路径 String imageUrl = "C:\\Users\\chuyunwei\\Desktop\\yully.jpg"; // 文件控件名称 String fileParamName = "images"; postData(modelApi, tokenStr, imageUrl, fileParamName); } // 发送post请求 public static void postData(String modelApi, String tokenStr, String imageUrl, String fileParamName) { String boundary = java.util.UUID.randomUUID().toString(); String prefix = "--", linend = "\r\n"; String charset = "UTF-8"; // 数据流 DataOutputStream outStream = null; // 连接 HttpsURLConnection connetion = null; // 读取图片的流 InputStream input = null; try { URL url = new URL(modelApi); connetion = (HttpsURLConnection) url.openConnection(); connetion.setReadTimeout(30 * 1000); // 缓存的最长时间 connetion.setDoInput(true);// 允许输入 connetion.setDoOutput(true);// 允许输出 connetion.setUseCaches(false); // 不允许使用缓存 connetion.setRequestMethod("POST"); connetion.setRequestProperty("connection", "keep-alive"); // 设置以二进制传输数据;multipart/form-data: 每个参数以 --boundary 开始 connetion.setRequestProperty("Content-Type", "multipart/form-data;Charsert=UTF-8;boundary=" + boundary); connetion.setRequestProperty("X-Auth-Token", tokenStr); File file = new File(imageUrl); // 设置内容参数 StringBuilder contentParam = new StringBuilder(prefix).append(boundary).append(linend) .append("Content-Disposition: form-data; name=" + fileParamName + "; filename=" + file.getName() + linend) .append("Content-Type: application/octet-stream; charset=" + charset).append(linend).append(linend); outStream = new DataOutputStream(connetion.getOutputStream()); outStream.write(contentParam.toString().getBytes()); input = new FileInputStream(file); byte[] buffer = new byte[1024]; int len = 0; while ((len = input.read(buffer)) != -1) { outStream.write(buffer, 0, len); } input.close(); outStream.write(linend.getBytes()); // 设置请求结束标志符: 以 --boundary-- 为结束符 byte[] endData = (prefix + boundary + prefix + linend).getBytes(); outStream.write(endData); outStream.flush(); // 获取响应结果流 InputStream connetionInput = connetion.getInputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connetionInput, charset)); // 按行读取响应结果 String line = ""; // 读取响应的结果值 StringBuffer resultBuffer = new StringBuffer(); while ((line = bufferedReader.readLine()) != null) { resultBuffer.append(line); } // 向控制台打印结果 System.out.println(resultBuffer.toString()); } catch (Exception e) { // 打印错误堆栈 e.printStackTrace(); } finally { // 关闭资源 closeResources(outStream, connetion, input); } } // 关闭资源 private static void closeResources(DataOutputStream outStream, HttpsURLConnection connetion, InputStream input) { if (input != null) { try { input.close(); } catch (IOException e) { e.printStackTrace(); } } if (outStream != null) { try { outStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (connetion != null) { connetion.disconnect(); } } } # 5. Demo补充说明 ## 5.1 注释说明 // 服务器url String modelApi = "https://XXX"; // token String tokenStr = "XXXX"; // 图片的绝对路径 String imageUrl = "C:\\Users\\chuyunwei\\Desktop\\yully.jpg"; // 文件控件名称 String fileParamName = "images"; Ⅰ. rl获取,控制台在线服务器调用指南TOP 页获取: ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202111/23/191342hsdt0d3jgrqyxae1.png) Ⅱ. token,调试过程直接调用: KeystoneCreateUserTokenByPassword接口获取IAM用户token: https://apiexplorer.developer.huaweicloud.com/apiexplorer/doc?product=IAM&api=KeystoneCreateUserTokenByPassword Ⅲ. 图片的绝对路径: 图片存放本地,直接使用本机的绝对路径进行获取。 Ⅳ. 文件控件名称,即为在线服务API输入图片的参数名称: ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202111/23/191414bzrwlsrtppjrirzr.png) # 6. 实测结果 ## 6.1 修改配置 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202111/23/191516au8a4eb8scpraqhs.png) ## 6.2 代码调试 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202111/23/191525ppdaxxrhwx4lipvr.png) 调试成功,返回结果。 # 7. 问题记录及解决办法 ## 7.1 服务未启动,运行报错 Ⅰ. 在线服务未启动,调试报错如下,重新启动服务即可正常请求。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202111/23/191653nmijbmix9linlbmo.png) ## 7.2 请求报401错误 Ⅰ. 查看错误码,判断401错误为鉴权问题导致,查看modelarts的认证鉴权方式帮助文档。可知请求token时,“auth.scope”的取值需要选择“project”。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202111/23/1917214vlvw9khc59ilept.png) Ⅱ. 我的token获取方式: ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202111/23/191729bgrihqsac0eoyrsl.png) Ⅲ. Modelart token获取方式:按照如下方式获取token后,请求正常。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202111/23/191739o1haypjnskpt4toa.png) # 8. 问题解决渠道说明 ## 8.1 华为云开发者技术支持界面 访问链接:https://support.developer.huaweicloud.com/feedback/#/ ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202111/23/191814czd0vyl5ygo08t6c.png) ## 8.2 华为云开发者论坛界面 访问链接:https://bbs.huaweicloud.com/forum/forum-1175-1.html ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202111/23/1918211hmoslfxm9en5fib.png)
  • [毕昇JDK] 【技术剖析】12. 毕昇 JDK 8 中 AppCDS 实现介绍
    ## 作者:伍家华 > 编者按:笔者通过在 Hive 的场景发现 AppCDS 技术存在的价值,然后分析了 AppCDS 的工作原理,并将 JDK 11 中的特性移植到毕昇 JDK 8,在移植过程中由于 JDK 8 和 JDK 11 在类加载实现有所不同,JDK 11 在加载过程中增强了安全性检查,为了达到相同的效果没有对 JDK 8 中的类加载进行修改,而是通过额外的安全检查保证共享类的安全性。最后笔者介绍了如何使用 AppCDS 以及使用的注意事项,希望对读者有所帮助。 基于某产品集群业务中有使用 Hive 场景,我们发现该集群在执行任务时会启动大量的 Java 进程,且进程很快就执行结束。对于这种情况一个有效的解决方法是让 Java 进程之间重用部分公共数据,从而减少 Java 进程产生公共数据的耗时。在 JDK 11 中支持 CDS 和 AppCDS,CDS 的全称是 Class-Data Sharing,CDS 的作用是可以让类被预处理放到一个归档文件中,后续 Java 程序启动的时候可以直接带上这个归档文件,这样 JVM 可以直接将这个归档文件映射到内存中,以节约应用启动的时间。AppCDS 是 CDS 的扩展,不止能够作用于 Boot Class Loader,App Class Loader 和自定义的 Class Loader 也都能够起作用,加大了 CDS 的适用范围 [1]。技术原理是让多个 Java 进程共享类的元数据,其基本原理如下所示: ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202111/11/104410z4rnlch0colqsajm.png) 左右两边分别都是一个 Java 进程,双方通过共享内存达到节约内存、减少类解析的目的。下面通过案例介绍一下我们发现的现象,然后再介绍类共享机制的内部原理。 # 1. 技术背景 ## 1.1 环境介绍 Hive on tez 集群,4 个节点,一个管理节点,其他三个节点作为工作节点。软件版本:Hadoop 3.1.0,hive 3.1.2,tez-0.9.1,ambari2.6,TPC-DS 标准测试套。硬件环境:Kunpeng 920,128 核,512G 内存。 ## 1.2 系统负载情况 运行 TPC-DS 自带的 sql8,使用 top 观察其中的一个节点的工作负载,发现启动了大量的 JVM 进程。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202111/11/104450m7cjjd1bzhuryedr.png) ## 1.3 热点分布 同时使用 perf 采集整机的热点数据,发现 JVM 的 C1, C2 编译线程占比很高,如下图所示。因此判断 hive sql 的 startup 和 warmup 阶段占比比较高,可以考虑从这两个方向优化。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202111/11/104507wlgt4bw1hwq11tpg.png) 考虑到目前 JVM 的 C2 代码比较难维护,也很难引进新的 feature。因此考虑看看在启动阶段有没有优化的可能。jdk1.8 带有 cds 功能,能够 share jdk 自带的 java class,能够减少 JVM 的类加载时间,因此首先尝试使用默认的 cds 功能,测试发现效果不明显。原因是 hive sql 执行过程中加载的类大部分是应用程序 classpath 下的类,jdk 自身的类占比很小,因此收益不明显。考虑到 jdk10 以后有了 AppCDS 功能,能够 share classpath 下的 class,因此考虑在 jdk1.8 上面实现 AppCDS 功能。 # 2. AppCDS 实现 毕昇 JDK 支持 AppCDS,即在原生 CDS 的基础上也支持用户自己程序 classpath 中的类共享。原生 CDS 只支持由 `Bootstrap classloader` 和 `Ext Classloader` 加载的 class,即 jdk 自带的 class 在多进程之间共享。但是在实际场景中,尤其是在使用了大量开源软件的情况下,用户指定 classpath 下的 jar 远远大于 jdk 自带的 class,这样 CDS 的实际效果比较有限。 AppCDS 能够扩大 class 共享的范围,从而在节省内存使用以及 JVM 的启动时间两个方面进一步提升效果。 ## 2.1 create class list 文件 java class 文件被 JVM 执行之前首先要被加载进 JVM 内存里面,作为 meta data 存储在 JVM 的 metaspace 内存区域。其中一个关键步骤就是解析 class 文件。JVM 内部有个 ClassFileParser 类,提供了 parseClassFile 方法,解析成功之后会生成一个对应 Klass。AppCDS 的第一步逻辑就是在类被解析完成之后,如果 class 不是匿名类,且 class 文件的 major version 大于 JAVA_1_5 Version,则会把 class 对应的 qualified name 写去到 list 文件中去。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202111/11/104531nijzq6lsdx6btjih.png) ## 2.2 create jsa 归档文件 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202111/11/104544ihisa4ev0ni6ndj7.png) 在这一步 JVM 会按行读取 appcds.lst 文件中内容,然后使用 App ClassLoader 去加载对应的 class。由于 Java classloader 自身的 delegate 机制,能够确保 jdk 自身的 class 也能够得到加载。Class 被加载之后存在 JVM 的 metaspace 区域,这个 metaspace 是 JVM Native Memory 的一部分,里面包含 klass, ConstantPool, Annotation, ConstMethod, Method, MethodData 等 meta 信息。 当 lst 文件中对应的 class 都被 JVM 加载完成之后,JVM 会把其对应的 metadata 写入到从虚拟地址 0x800000000 开始的内存区域,其格式是 JVM 内部私有的一种表示,然后再把这部分数据 dump 到归档文件中。 ## 2.3 与 JDK 11 实现的差别 与 JDK 11 中的 AppCDS 实现差别主要体现在加载用户指定的 class 逻辑上。当加载用户 class 时,是需要计算获取一个 ProtectionDomain 来做安全验证的。JDK 11 是直接在 hotspot 中使用 JavaCalls 模块构造这个 ProtectionDomain,而毕昇 JDK 8 是在 Java 的 ClassLoader 中提供了一个 `getProtectionDomainInternal` 函数来获取,并在加载 class 的时候使用 JavaCalls 调用这个 java 方法。 # 3. AppCDS 使用说明 ## 3.1 创建 lst 文件 启动 JVM 的时候添加 `- Xshare:off` 和 `- XX:+DumpLoadedClassList=/path/to/class.lst` 这两个选项。这里比较重要的是第二个选项,这个选项同时支持 %P,可以按进程生成 class.lst 文件,生成的文件名会带上 JVM 进程的 pid。class.lst 本质上是个纯文本文件,里面记录 JVM 运行过程中加载的 class 列表。在 java 程序被 JVM 执行的过程中,会不断地从 classpath 中加载 class,并在 JVM 内部创建对应的 klass 对象。Klass 对象创建成功之后 JVM 会把 class 在 JVM 内部的 qualified name 写入到 class.lst 文件中,比如 `java.lang.Objectd` 对应的是 java/lang/Object。 **使用例子:** ```Bash java -Xms16M -Xmx16M -XX:+UseG1GC -cp test.jar -Xshare:off -XX:+UseAppCDS -XX:DumpLoadedClassList=appcds.lst com.example.App ``` ## 3.2 创建 archive 文件 第二步:创建 cds 归档文件。使用方式: ```Bash java -Xms16M -Xmx16M -XX:+UseG1GC -cp test.jar -Xshare:dump -XX:+UseAppCDS -XX:SharedClassListFile=appcds.lst -XX:SharedArchiveFile=appcds.jsa com.example.App ``` ## 3.3 使用 archive 文件 使用示例: ```Bash java -Xms16M -Xmx16M -XX:+UseG1GC -cp test.jar -Xshare:on -XX:+UseAppCDS -XX:SharedArchiveFile=appcds.jsa com.example.App ``` 第三步:JVM 在启动的过程中会把 jsa mmap 到内存中,然后在触发类加载时候 JVM 会首先尝试从这块 mmap 进来的内存中去获取 klass 对象,如果获取到则会更新 JVM 内部的 SystemDictionary,以后再来获取对应的 klass 对象则不需要从 jsa 中获取。如果获取失败,JVM 则会走正常的类加载流程,尝试从 classpath 中加载对应的 class 文件,解析,链接,初始化,然后再放入 SystemDictionary 中。 # 4. AppCDS 效果 TPC-DS 测试套的 10 个 sql 在 5T 数据的场景下测试了一下 AppCDS 的效果,结果收益好,最低是 8.42% 的性能提升,最高是 26.9% 的性能提升。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202111/11/104759jowrhg8agxnaksbg.png) # 5. 注意事项 使用 AppCDS 三部曲过程中要保持 JVM 版本、JAVA_HOME 路径一致,不然会校验失败,无法启动 JVM。 在第二步加载 class 并创建 jsa 归档文件的时候,JVM 会记录 class 的 fingerprint 信息 (相当于 hash 值),在第三步使用 jsa 中的 class 信息时会校验这个 fingerprint 信息,因此如果业务侧代码发生变更,要重新部署的话,jsa 归档文件要重新制作。 使用 AppCDS 或者 CDS 的时候不能 debug java 程序。因为 debug 的时候 jvmti 会修改 class 对应的内容,而根据第二点,必然会导致 fingerprint 不一致。 目前 AppCDS 并不支持 `Custom ClassLoader`,因此在 tomcat、jetty、SpringBoot 这些使用较多 `Custom ClassLoader` 场景的,整体收益跟原生 CDS 应该差不多,class 可以 share 的范围仅仅多了一些 Application 自身的 boot class。 # 后记 如果遇到相关技术问题(包括不限于毕昇 JDK),可以进入毕昇 JDK 社区查找相关资源(点击[阅读原文](https://mp.weixin.qq.com/s/QVljVWthj9mvAL0HAiWFcw)进入官网),包括二进制下载、代码仓库、使用教学、安装、学习资料等。毕昇 JDK 社区每双周周二举行技术例会,同时有一个技术交流群讨论 GCC、LLVM、JDK 和 V8 等相关编译技术,感兴趣的同学可以添加如下微信小助手,回复 Compiler 入群。 ![](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202111/11/104833lyyanphull8o7upu.jpg) # 参考 [1] https://juejin.cn/post/6844903581246914574 原文转载自 openEuler-[毕昇 JDK 8 中 AppCDS 实现介绍](https://mp.weixin.qq.com/s/QVljVWthj9mvAL0HAiWFcw)
总条数:2301 到第 页
上滑加载中