Java进阶1-JVM虚拟机 JVM在字节码上的使用方法
1. JVM简述
(资料图片)
JVM是Java Virtual Machine的缩写。它是一种基于计算设备的规范,是一台虚拟机,即虚构的计算机。 JVM屏蔽了具体操作系统平台的信息(显然,就像是我们在电脑上开了个虚拟机一样),当然,JVM执行字节码时实际上还是要解释成具体操作平台的机器指令的。 如类加载机制、运行时数据区、垃圾回收机制等; 官网:https://www.oracle.com/java/technologies/javase/vmoptions-jsp.html
2. 字节码
2.1 字节码由来
Java 所有的指令有 200 个左右,一个字节( 8 位)可以存储 256 种不同的指令信息,一个这样的字节称为字节码( Bytecode )
JVM 将字节码解释执行,屏蔽对底层操作系统的依赖,JVM也可以将字节码编译执行,如果是热点代码,会通过JIT 动态地编译为机器码,提高执行效率
JVM在字节码上也设计了一套操作码助记符,使用特殊单词来标记这些数字。 加载或存储指令 、运算指令、类型转换指令、对象创建与访问指令、操作栈管理指令、方法调用与返回指令。
2.2 源码转化成字节码
词法解析是通过空格分隔出单词 、操作符、控制符等信息 , 将其形成 token 信息流 ,传递给语法解析器。 在语法解析时,把词法解析得到的 token 信息流按照 Java 语法规则组装成一棵语法树 , 如图 4-2 虚线框所示。 在语义分析阶段 , 需要检查关键字的使用是否合理、类型是否匹配、作用域是否正确等。 当语义分析完成之后,即可生成字节码。
2.2 执行三种模式
字节码必须通过类加载过程加载到 JVM 环境后,才可以执行。执行有三种模式:第一,解释执行;第二,JIT 编译执行;第三, JIT 编译与解释混合执行(主流 JVM默认执行模式)。混合执行模式的优势在于解释器在启动时先解释执行,省去编译时间。随着时间推进 , JVM 通过热点代码统计分析 , 识别高频的方法调用、循环体、公共模块等,基于强大的 JlT 动态编译技术,将热点代码转换成机器码,直接交给 CPU执行。 JIT 的作用是将 Java 字节码动态地编译成可以直接发送给处理器指令执行的机器码。简要流程如图 4-3 所示。 注意解释执行与编译执行在线上环境微妙的辩证关系。机器在热机状态可以承受的负载要大于冷机状态(刚启动时 ),如果以热机状态时的流量进行切流 , 可能使处于冷机状态的服务器因无法承载流量而假死。 刚启动的 JVM 均是解释执行,还没有进行热点代码统计和 JIT 动态编译。
3. 类加载过程
3.1 类加载流程
1、Load加载(读取二进制流转特定数据结构) 2、Link链接( 验证-详细校验如类型、常量、静态变量等。 准备-为静态变量分配内存。 解析-确保类与类之间的相互引用正确性,完成内存结构布局) 3、Init初始化(执行类构造器完成类的初始化) 4、解析执行直接给CPU、JIT动态编译机器码再给CPU 类加载是一个将 . class 字节码文件实例化成 Class 对象并进行相关初始化的过程。 全小写的 class 是关键字,用来定义类,而首字母大写的 Class ,它是所有 class 的类。** 问题:**为什么这个抽象还是另外一个类 Class 的对象? 示例代码如下:
/** * @author cmy * @version 1.0 * @date 2022/6/29 0029 13:43 * @description 类加载过程测试 */public class ClassTest {//数组类型有一个魔法属性:length来获取数组长度 private static int[] array=new int[3]; private static int length=array.length; //任何小写class定义的类,也有一个魔法属性:class,来获取此类的大写Class类对象 private static Classone=One.class; private static Classanother=Another.class; public static void main(String[] args) throws Exception {//通过newInstance方法创建One和 Another的类对象(第1处) One oneObject=one.newInstance(); oneObject.call(); Another anotherObject=another.newInstance(); anotherObject.speak(); //通过one这个大写的Class对象,反射方式获取私有成员属性对象Field(第2处) Field privateFieldInOne = one.getDeclaredField("inner"); //设置私有对象可以访问和修改(第3处) privateFieldInOne.setAccessible(true); privateFieldInOne.set(oneObject,"world changed"); //成功修改类的私有属性inner变量值为world changed. System.out.println(oneObject.getInner()); }}class One{private String inner="time files."; public void call(){System.out.println("hello world"); } public String getInner(){return inner; }}class Another{public void speak(){System.out.println("easy coding"); }}
第1处说明new 是强类型校验 , 可以调用任何构造方法 , 在使用new 操作的时候,这个类可以没有被加载过。 Class 类下的 newInstance是弱类型,只能调用无参数构造方法,如果没有默认构造方法,就抛出InstantiationException 异常,如果此构造方法没有权限访问,则抛出IllegalAccessException 异常。 第2处说明使用类似的方式获取其他声明 , 如注解、方法等,如图4.5所示。 第3处说明问题:private 成员在类外是否可以修改?通过 setAccessible(true) 操作,即可使用大写 C lass 类的 set 方法修改其值。
3.2 类加载器实现机制
/** * 查看本地类加载器的方式如下 */ //正在使用得类加载器sun.misc.Launcher$AppClassLoader@18b4aac2 ClassLoader c = One.class.getClassLoader(); //AppClassLoader的父类加载器是ExtensionClassLoader JDK1.9之前 ClassLoader c1 = c.getParent(); //ExtClassLoader父类加载器(最高一层)Bootstrap C++实现 返回null ClassLoader c2 = c1.getParent(); System.out.println(c); System.out.println(c1); System.out.println(c2);
低层次的当前类加载器,不能覆盖更高层次类加载器已经加载的类。 如图 4-6 所示,左侧绿色箭头向上逐级询问是否已加载此类,直至 Bootstrap ClassLoader ,然后向下逐级尝试是否能够加载此类,如果都加载不了,则通知发起加载请求的当前类加载器 ,准予加载。 通过如下代码可以查看 Bootstrap 所有已经加载的类库:
/** * 通过如下代码可以查看BootstrapClassLoader所有已经加载的类库: */ URL[] urLs = Launcher.getBootstrapClassPath().getURLs(); for (java.net.URL url:urLs) {System.out.println(url.toExternalForm()); }
在JVM中增加如下启动参数 , 则能通过 Class.forName 正常读取到指定类 , 说明此参数可以增加Bootstrap 的类加载路径:
- Xbootclasspath/a:/Users/yangguanbao/book/easyCoding/byJdk11/src
如果想在启动时观察加载了哪个jar包中的哪个类 ,可以增加-XX:+TraceClassLoading参数
- XX:+TraceClassLoading
3.3 自定义类加载器
学习类加载器的实现机制后 , 双亲委派模型并非强制模型, 用户可以自定义类加载器 。问题:在什么情况下需要自定义类加载器呢? ** ** 隔离加载类、修改类加载方式、扩展加载源、防止源码泄露。
实现自定义类加载器的步骤,继承ClassLoader,重写 findClass()方法,调用defineClass()方法。一个简单的类加载器实现的示例代码如下:
/** * @author cmy * @version 1.0 * @date 2022/6/29 0029 15:34 * @description 自定义类加载器 * * 自定义类加载器步骤: * 继承ClassLoader * 重写findClass()方法 * 调用defineClass()方法 */public class CustomClassLoader extends ClassLoader {private String classpath; public CustomClassLoader(String classpath) {this.classpath = classpath; } @Override protected Class findClass(String name) throws ClassNotFoundException {try {byte[] bytes = getClassFromCustomPath(name); return defineClass(name, bytes, 0, bytes.length); } catch (IOException e) {e.printStackTrace(); throw new ClassNotFoundException(); } } private byte[] getClassFromCustomPath(String name) throws IOException {//从自定义路径中加载指定类 FileInputStream fis = new FileInputStream(classpath + File.separator + name.replace(".", File.separator).concat(".class")); byte[] bytes = new byte[fis.available()]; fis.read(bytes); fis.close(); return bytes; } public static void main(String[] args) {CustomClassLoader customClassLoader = new CustomClassLoader("F:\\IDEA2022\\workmenu\\SoftwareTools\\src\\main\\java"); try {Class clazz = customClassLoader.loadClass("Test"); //调用的静态方法 clazz.getDeclaredMethod("say").invoke(clazz); Object o = clazz.newInstance(); Method print = clazz.getDeclaredMethod("print", String.class); print.invoke(o, "调用的对象方法"); //自定义类加载器 System.out.println(clazz.getClassLoader()); //AppClassLoader System.out.println(clazz.getClassLoader().getParent()); //ExtClassLoader System.out.println(clazz.getClassLoader().getParent().getParent()); //BootstrapLoader System.out.println(clazz.getClassLoader().getParent().getParent().getParent()); }catch (Exception e){e.printStackTrace(); } }}//https://blog.csdn.net/weixin_42759726/article/details/114030153
//javac编译后,记得删除Test.java比较路径寻找和Test.class冲突public class Test {public static void say() {System.out.println("this is a static method!"); } public void print(String s) {System.out.println("printing:"+s); }}
按某种规则 jar 包的版本被统←指定 ,导致某些类存在包路径、类名相同 的情况 , 就会引起类冲突 ,导致应用程序出现异常。主流的容器类框架都会自定义类加载器,实现不同中间件之间的类隔离 , 有效避免了类冲突。
4. 内存布局(运行时数据区域)
前面回顾连接
在类加载过程第二步Link链接的解析阶段,解析类和方法确保类与类之间的相互引用正确性,完成内存 结构布局。
4.1 内存布局简介
Java 程序在运行时,会为 JVM 单独划出一块内存区域,而这块内存区域又可以再次划分出一块运行时数据区,运行时数据区域大致可以分为五个部分:
4.2 Heap堆区
**Heap堆区作用:**Heap 是 OOM 故障最主要的发源地 , 它存储着几乎所有的实例对象, 堆由垃圾收集器自动回收 , 堆区由各子线程共享使用。 堆的内存空间既可以固定大小 , 也可以在运行时动态地调整。
比如 -Xms256M -Xmxl024M ,其中 -X 表示它是 JVM 运行参数, ms 是 memory start 的简 称, mx 是 memory max 的简称,分别代表最小堆容量和最大堆容量。 一般最大和最小一样。避免在GC后调整堆大小时带来的额外压力。
堆分成两大块:新生代和老年代。新生代= 1 个 Eden 区+ 2 个Survivor 区。
当 Eden区装填满的时候 , 会触发 Young Garbage Collection , 即 YGC。垃圾回收的时候 , 在 Eden 区实现清除策略 , 没有被引用的对象则直接回收。依然存活的对象会被移送到 Survivor 区。
**问题:**Survivor 区分为 S0和 S1两块内存空间 , 送到哪块空间呢? 每次 YGC 的时候, 它们将存活的对象复制到未使用的那块空间,然后将当前正在使用的空间完全清除 , 交换两块空间的使用状态。
**问题:**如何防止对象没有进取心? 每个对象都有一个计数器,每次 YGC 都会加1。 -XX:MaxTenuringThreshold 参数能配置计数器的值到达某个阀值的时候 , 对象从新生代晋升至老年代。
对象分配与简要GC流程图如图4-9所示。 图 的 中,如果 Survivor 区无法放下,或者超大对象的闹值超过上限,则尝试在老年代中进行分配 ; 如果老年代也无法放下,则会触发 Full Garbage Collection , 即FGC。如果依然无法放下, 则抛出 OOM。堆内存出现 OOM 的概率是所有内存耗尽异常中最高的。出错时的堆内信息对解决问题非常有帮助 , 所以给JVM设置运行参数 -XX:+HeapDumpOnOutOfMemoryError,让JVM遇到OOM 异常时能输出堆内信息,特别是对相隔数月才出现的 OOM 异常尤为重要。
4.3 Metaspace (元空间)
元空间作用:存储常量池、方法元信息、类元信息。字符串常量String存在堆内存。
元空间发展:源码解析和示例代码基本采用 JDK11版本, JVM则为 Hotspot。在 JDK7 及之前的版本中,只有 Hotspot才有 Perm 区,译为永久代 , 它在启动时固定大小,很难进行调优。动态加载类过多,容易产生 Perm 区的 OOM。为了解决Perm 区的 OOM, 需要设定运行参数 -XX:MaxPermSize= 1280m。
永久代在垃圾回收过程中还存在诸多问题。 JDK8 使用元空间替换永久代。在 JDK8 及以上版本中,设定 MaxPermSize 参数, JVM在启动时并不会报错。
区别于永久代 , 元空间在本地内存中分配。在 JDK8 里, Perm 区 中的所有内容 中字符串常量移至堆内存,其他内容包括类元信息、字段、静态属性、方法、常量等 都移动至无空间内。
图 4-10 中显示在常量池中的 String, 其实际对象是被保存在堆内存中的。
4.4 JVM Stack (虚拟机栈)
**虚拟机栈作用:描述JAVA方法执行的内存区域。**方法调用到执行完成~入栈到出栈的过程。栈顶的帧称为栈帧,正在执行的方法称为当前方法,栈帧是方法运行的基本结构。StackOverflowError表示请求的栈溢出,内存耗尽。 栈帧在整个 JVM 体系中的地位颇高, 包括局部变量表、操作栈、动态连接、方法返回地址等。
1 局部变量表2 操作栈
public int simpleMethod(){//将常量13压入操作栈、保存到局部变量表的slot_1中 int x=13; //将常量14压入操作栈、保存到局部变量表的slot_2中 int y=14; //将slot_1元素压入操作栈,将slot_2元素压入操作栈, //再取出来到CPU中加法,并压回操作栈,把栈顶结果保存到局部变量表的slot_3中 int z= x+y; //返回栈顶元素值 return z;}
** 3 动态链接** 每个枝帧中包含一个在常量池中对当前方法的引用 , 目的是支持方法调用过程的动态连接。 4 方法返回地址
4.5 Native Method Stacks (本地方法栈)
本地方法栈作用:虚拟机栈“主内 ”, 而本地方法栈“主外”。本地方法栈为 Native 方法服务。本地方法可以通过 JNI ( Java Native Int rface )来访问虚拟机运行时的数据区 ,甚至可以调用寄存器,具有和 JVM 相同的能力和权限。对于内存 不足的情况 本地方法枝还是会抛出 native heap OutOfMemory。
4.6 Program Counter Register(程序计数寄存器)
程序计数寄存器作用:CPU 只有把数据装载到寄存器才能够运行。保证在多线程并发执行过程中,保证分毫无差。**问题:**由于CPU时间片轮限制,众多线程在并发执行过程中,导致经常中断或恢复,如何保证分毫无差呢? 每个线程在创建后,都会产生 自己的程序计数器和栈帧,程序计数器用来存放执行指令的偏移量和行号指示器等, 线程执行或恢复都要依赖程序计数器。程序计数器在各个线程之间互不影响,此区域 也不会发生内存溢出异常。
4.7 运行时数据区域总结
1 Heap堆区作用:Heap 是 OOM 故障最主要的发源地 ,它存储着几乎所有的实例对象。堆由垃圾收集器自动回收 , 堆区由各子线程共享使用。 堆的内存空间既可以固定大小 , 也可以在运行时动态地调整。 2 元空间作用:存储常量池、方法元信息、类元信息。字符串常量String存在堆内存。3 虚拟机栈作用:描述JAVA方法执行的内存区域。方法调用到执行完成~入栈到出栈的过程。栈顶的帧称为栈帧,正在执行的方法称为当前方法,栈帧是方法运行的基本结构。StackOverflowError表示请求的栈溢出,内存耗尽。 4 本地方法栈作用:虚拟机栈“主内 ”, 而本地方法栈“主外”。本地方法栈为 Native 方法服务。本地方法可以通过 JNI ( Java Native Int rface )来访问虚拟机运行时的数据区 ,甚至可以调用寄存器。 5 程序计数寄存器作用:CPU 只有把数据装载到寄存器才能够运行。保证在多线程并发执行过程中,保证分毫无差。每个线程在创建后,都会产生 自己的程序计数器和栈帧,程序计数器用来存放执行指令的偏移量和行号指示器等。
5. 对象实例化
Java 是面向对象的静态强类型语言,根据某个类声明一个引用变量指向被创建的对象。 问题:在实例化对象的过程中,JVM会发生什么化学反应?
5.1 从字节码的进行分析
1、NEW类加载 2、DUP栈顶复制引用变量 3、INVOKESPECIAL初始化
5.2 从执行步骤的角度分析
1、确认类元信息是否存在 2、分配对象内存 3、设定默认值 4、设置对象头 5、执行init方法
6. 垃圾回收
垃圾回收( Garbage Collection, GC )。垃圾回收的主要目的是清除不再使用的对象,自动释放内存。
6.1 对象是否存活的标准
问题:GC 是如何判断对象是否可以被回收的呢?为了判断对象是否存活 , JVM 引人了GC Roots。某个失去任何引用的对象,或者两个互相环岛状循环引用的对象等,可以直接回收。 问题:什么对象可以作为 GC Roots 呢?比如类静态属性中引用的对象、常量引用的对象、虚拟机栈中寻引用的对象、本地方法栈中引用的对象等。
6.2 垃圾回收的相关算法
“标记-清除算法”。
该算法从GC Roots出发,依次标记有引用关系的对象,将没有被标记的对象清除。此算法会带来大量的空间碎片,要分配较大连续空间容易出现FGC。
“标记-整理算法”。
该算法从GC Roots出现标记存活对象,然后将存活对象整理导内存空间的一端,形成已使用的连续空间,最后把已使用空间外的部分全部清理掉。
“Mark-Copy算法”(主流YGC算法新生代垃圾回收)。也称标记-复制
为了并行地标记和整理,将空间分为两块,每次只激活一块。垃圾回收时只需要把存活对象复制到另一块未激活空间,将未激活空间标记为已激活,将已激活空间标记为未激活,然后清除原空间对象,如此反复置换清除。每次只使用堆区一块Eden区和Survior区,减少了内存空间的浪费。
6.2 垃圾回收器
垃圾回收器( Garbage Collector )是实现垃圾回收算法并应用在 JVM 环境中的内存管理模块 。
Serial 回收器
Serial 回收器是一个主要应用于 YGC 的垃圾回收器,采用串行单线程的方式完成 GC 任务。其中"Stop The World"简称STW,即垃圾回收的某个阶段会暂停整个应用程序的执行。标记-复制算法YGC
CMS 回收器
CMS 回收器 (Concurrent Mark Sweep Collector) 是回收停顿时间比较短、目前比较常用的垃圾回收器,采用"标记-清除算法"。 通过初始标记(Initial Mark) 、并发标记(Concurrent Mark )、重新标记(Remark)、并发清除(Concurrent Sweep)四个步骤完成垃圾回收工作。
G1回收器
Hotspot 在 JDK7 中 推出了新一代 G1 ( Garbage-First Garbage Collector ) 垃圾回收 ,通过去-XX:+UseG1GC参数启用。G1采用"Mark-Copy算法"。 GI 将 Java 堆空间分割成了若干相同大小的 区域,即 region ,包括 Eden 、Survivor 、 Old 、 Humongous 四种类型。
7. JVM监控工具
7.1 jconsole
Jconsole(Java Monitoring and Management Console)是从 java5 开始,在 JD K中自带的 java 监控和管理控制台,用于对 JVM 中内存,线程和类等的监控,是一个基于 JMX(java management extensions)的 GUI 性能监测工具。
7.2 VisualVM
VisualVM(All-in-One Java Troubleshooting Tool)是功能最强大的运行监视和故障处理程序之一,曾经在很长一段时间内是 Oracle 官方主力发展的虚拟机故障处理工具。
8. JVM 调优选择
8.1 选择合适的垃圾回收器
CPU 单核:那么毫无疑问 Serial 垃圾收集器是你唯一的选择;CPU 多核:关注吞吐量 ,那么选择 PS+PO 组合;JDK8默认CPU 多核:关注用户停顿时间,JDK 版本 1.6 或者 1.7,那么选择 CMS;CPU 多核:关注用户停顿时间,JDK1.8 及以上,JVM 可用内存 6G 以上,那么选择 G1。
参数配置:
//设置Serial垃圾收集器(新生代)开启:-XX:+UseSerialGC//设置PS+PO,新生代使用功能Parallel Scavenge 老年代将会使用Parallel Old收集器开启 -XX:+UseParallelOldGC//CMS垃圾收集器(老年代)开启 -XX:+UseConcMarkSweepGC//设置G1垃圾收集器 开启 -XX:+UseG1GC
8.2 调整内存大小
现象:垃圾收集频率非常频繁。 原因:如果内存太小,就会导致频繁的需要进行垃圾收集才能释放出足够的空间来创建新的对象,所以增加堆内存大小的效果是非常显而易见的。 注意:如果垃圾收集次数非常频繁,但是每次能回收的对象非常少,那么这个时候并非内存太小,而可能是内存泄露导致对象无法回收,从而造成频繁 GC。 参数配置:
//设置堆初始值 指令1:-Xms2g 指令2:-XX:InitialHeapSize=2048m //设置堆区最大值 指令1:`-Xmx2g` 指令2: -XX:MaxHeapSize=2048m //新生代内存配置 指令1:-Xmn512m 指令2:-XX:MaxNewSize=512m
8.3 设置符合预期的停顿时间
现象:程序间接性的卡顿 原因:如果没有确切的停顿时间设定,垃圾收集器以吞吐量为主,那么垃圾收集时间就会不稳定。 注意:不要设置不切实际的停顿时间,单次时间越短也意味着需要更多的 GC 次数才能回收完原有数量的垃圾. 参数配置:
//GC停顿时间,垃圾收集器会尝试用各种手段达到这个时间 -XX:MaxGCPauseMillis
8.4 调整内存区域大小比率
现象:某一个区域的GC频繁,其他都正常。 原因:如果对应区域空间不足,导致需要频繁GC来释放空间,在JVM堆内存无法增加的情况下,可以调整对应区域的大小比率。 注意:也许并非空间不足,而是因为内存泄造成内存无法回收,从而导致 GC 频繁。 参数配置:
//survivor区和Eden区大小比率 指令:-XX:SurvivorRatio=6 //S区和Eden区占新生代比率为1:6,两个S区2:6 //新生代和老年代的占比 -XX:NewRatio=4 //表示新生代:老年代 = 1:4 即老年代占整个堆的4/5;默认值=2
8.5 调整对象升老年代的年龄
现象:老年代频繁 GC,每次回收的对象很多。 原因:如果升代年龄小,新生代的对象很快就进入老年代了,导致老年代对象变多,而这些对象其实在随后的很短时间内就可以回收,这时候可以调整对象的升级代年龄,让对象不那么容易进入老年代解决老年代空间不足频繁 GC 问题。 注意:增加了年龄之后,这些对象在新生代的时间会变长可能导致新生代的 GC 频率增加,并且频繁复制这些对象新生的 GC 时间也可能变长。 配置参数:
//进入老年代最小的GC年龄,年轻代对象转换为老年代对象最小年龄值,默认值7 -XX:InitialTenuringThreshol=7
8.6 调整大对象的标准
现象:老年代频繁 GC,每次回收的对象很多,而且单个对象的体积都比较大。 原因:如果大量的大对象直接分配到老年代,导致老年代容易被填满而造成频繁 GC,可设置对象直接进入老年代的标准。 注意:这些大对象进入新生代后可能会使新生代的 GC 频率和时间增加。 配置参数:
//新生代可容纳的最大对象,大于则直接会分配到老年代,0代表没有限制。 -XX:PretenureSizeThreshold=1000000
8.7 调整GC的触发时机
现象:CMS,G1 经常 Full GC,程序卡顿严重。 原因:G1 和 CMS 部分 GC 阶段是并发进行的,业务线程和垃圾收集线程一起工作,也就说明垃圾收集的过程中业务线程会生成新的对象,所以在 GC 的时候需要预留一部分内存空间来容纳新产生的对象,如果这个时候内存空间不足以容纳新产生的对象,那么JVM就会停止并发收集暂停所有业务线程(STW)来保证垃圾收集的正常运行。这个时候可以调整GC触发的时机(比如在老年代占用 60% 就触发 GC),这样就可以预留足够的空间来让业务线程创建的对象有足够的空间分配。 注意:提早触发 GC 会增加老年代 GC 的频率。 配置参数:
//使用多少比例的老年代后开始CMS收集,默认是68%,如果频繁发生SerialOld卡顿,应该调小 -XX:CMSInitiatingOccupancyFraction //G1混合垃圾回收周期中要包括的旧区域设置占用率阈值。默认占用率为 65% -XX:G1MixedGCLiveThresholdPercent=65
8.8 调整 JVM本地内存大小
现象:GC 的次数、时间和回收的对象都正常,堆内存空间充足,但是报 OOM 原因:JVM 除了堆内存之外还有一块堆外内存,这片内存也叫本地内存,可是这块内存区域不足了并不会主动触发 GC,只有在堆内存区域触发的时候顺带会把本地内存回收了,而一旦本地内存分配不足就会直接报 OOM 异常。 注意:本地内存异常的时候除了上面的现象之外,异常信息可能是 OutOfMemoryError:Direct buffer memory。解决方式除了调整本地内存大小之外,也可以在出现此异常时进行捕获,手动触发 GC(System.gc())。 配置参数:
XX:MaxDirectMemorySize
9. JVM 调试实战
为什么要调整JVM
JVM调优背景
生产环境中的问题 生产环境发生了内存溢出该如何处理? 生产环境应该给服务器分配多少内存合适? 如何对垃圾回收器的性能进行调优? 生产环境 CPU 负载飙高该如何处理? 生产环境应该给应用分配多少线程合适? 不加 log,如何确定请求是否执行了某一行代码? 不加 log,如何实时查看某个方法的入参与返回值?
为什么要调优
防止出现 OOM解决 OOM减少 Full GC 出现的频率
不同阶段的考虑
上线前项目运行阶段线上出现 OOM
JVM调优方案
监控的依据
运行日志异常堆栈GC 日志线程快照堆转储快照
调优的大方向
合理地编写代码充分并合理的使用硬件资源合理地进行 JVM 调优
JVM性能优化的步骤
第 1 步:性能监控
GC 频繁 cpu load 过高 OOM 内存泄露 死锁 程序响应时间较长
第 2 步:性能分析
打印 GC 日志,通过 GCviewer 或者 Universal JVM GC analyzer - Java Garbage collection log analysis made easy 来分析异常信息 灵活运用命令行工具、jstack、jmap、jinfo 等 dump 出堆文件,使用内存分析工具分析文件 使用阿里 Arthas、jconsole、JVisualVM 来实时查看 JVM 状态 jstack 查看堆栈信息
第 3 步:性能调优
适当增加内存,根据业务背景选择垃圾回收器优化代码,控制内存使用增加机器,分散节点压力合理设置线程池线程数量使用中间件提高程序效率,比如缓存、消息队列等其他……
性能评价/测试指标
**1 停顿时间(或响应时间):**提交请求和返回该请求的响应之间使用的时间,一般比较关注平均响应时间。常用操作的响应时间列表:
2 垃圾回收环节:
暂停时间:执行垃圾收集时,程序的工作线程被暂停的时间。-XX:MaxGCPauseMillis 表示每次GC最大的停顿毫秒
3 吞吐量
对单位时间内完成的工作量(请求)的量度在 GC 中:运行用户代码的事件占总运行时间的比例(总运行时间:程序的运行时间+内存回收的时间)吞吐量为 1-1/(1+n),其中-XX::GCTimeRatio=n
4 并发数
同一时刻,对服务器有实际交互的请求数
5 内存占用
Java 堆区所占的内存大小
6 相互间的关系
以高速公路通行状况为例
吞吐量:每天通过高速公路收费站的车辆的数据并发数:高速公路上正在行驶的车辆的数目响应时间:车速
9.1 网站流量浏览量暴增后,网站反应页面响很慢
1、问题推测:在测试环境测速度比较快,但是一到生产就变慢,所以推测可能是因为垃圾收集导致的业务线程停顿。 2、定位:为了确认推测的正确性,在线上通过 jstat -gc 指令 看到 JVM 进行 GC 次数频率非常高,GC 所占用的时间非常长,所以基本推断就是因为 GC 频率非常高,所以导致业务线程经常停顿,从而造成网页反应很慢。 3、解决方案:因为网页访问量很高,所以对象创建速度非常快,导致堆内存容易填满从而频繁 GC,所以这里问题在于新生代内存太小,所以这里可以增加 JVM 内存就行了,所以初步从原来的 2G 内存增加到 16G 内存。 4、第二个问题:增加内存后的确平常的请求比较快了,但是又出现了另外一个问题,就是不定期的会间断性的卡顿,而且单次卡顿的时间要比之前要长很多。 5、问题推测:之前的优化加大了内存,所以推测可能是因为内存加大了,从而导致单次 GC 的时间变长从而导致间接性的卡顿。 6、定位:还是通过 jstat -gc 指令 查看到 的确 FGC 次数并不是很高,但是花费在 FGC 上的时间是非常高的,根据 GC 日志 查看到单次 FGC 的时间有达到几十秒的。 7、解决方案:因为 JVM 默认使用的是 PS+PO 的组合,PS+PO 垃圾标记和收集阶段都是 STW,所以内存加大了之后,需要进行垃圾回收的时间就变长了,所以这里要想避免单次 GC 时间过长,所以需要更换并发类的收集器,因为当前的 JDK 版本为 1.7,所以最后选择 CMS 垃圾收集器,根据之前垃圾收集情况设置了一个预期的停顿的时间,上线后网站再也没有了卡顿问题。
9.2 后台导出数据引发的 OOM
问题描述:公司的后台系统,偶发性的引发 OOM 异常,堆内存溢出。 1、因为是偶发性的,所以第一次简单的认为就是堆内存不足导致,所以单方面的加大了堆内存从 4G 调整到 8G。 2、但是问题依然没有解决,只能从堆内存信息下手,通过开启了 -XX:+HeapDumpOnOutOfMemoryError 参数 获得堆内存的 dump 文件。 3、VisualVM 对堆 dump 文件进行分析,通过 VisualVM 查看到占用内存最大的对象是 String 对象,本来想跟踪着 String 对象找到其引用的地方,但 dump 文件太大,跟踪进去的时候总是卡死,而 String 对象占用比较多也比较正常,最开始也没有认定就是这里的问题,于是就从线程信息里面找突破点。 4、通过线程进行分析,先找到了几个正在运行的业务线程,然后逐一跟进业务线程看了下代码,发现有个引起我注意的方法,导出订单信息。 5、因为订单信息导出这个方法可能会有几万的数据量,首先要从数据库里面查询出来订单信息,然后把订单信息生成 excel,这个过程会产生大量的 String 对象。 6、为了验证自己的猜想,于是准备登录后台去测试下,结果在测试的过程中发现到处订单的按钮前端居然没有做点击后按钮置灰交互事件,结果按钮可以一直点,因为导出订单数据本来就非常慢,使用的人员可能发现点击后很久后页面都没反应,结果就一直点,结果就大量的请求进入到后台,堆内存产生了大量的订单对象和 EXCEL 对象,而且方法执行非常慢,导致这一段时间内这些对象都无法被回收,所以最终导致内存溢出。 7、知道了问题就容易解决了,最终没有调整任何 JVM 参数,只是在前端的导出订单按钮上加上了置灰状态,等后端响应之后按钮才可以进行点击,然后减少了查询订单信息的非必要字段来减少生成对象的体积,然后问题就解决了。
9.3 Window JVM调优
查询JDK所用虚拟机
java version "1.8.0_91"Java(TM) SE Runtime Environment (build 1.8.0_91-b14)Java HotSpot(TM) 64-Bit Server VM (build 25.91-b14, mixed mode)//支持 Java 8, 使用的是 Oracle 的64位HotSpot虚拟机。//HotSpot VM 是 OracleJDK / SunJDK 以及 OpenJDK 里的 JVM 实现。使用最广泛,JDK默认安装的。
Java问题诊断和排查工具(查看JVM参数、内存使用情况及分析等)
常用查询命令
JPS (打印Java进程信息)
使用场景 : 查看当前机器的所有Java进程信息(可追踪到应用进程ID 、启动类名、文件路径。)。jps 显示当前所有java进程pid的命令jps -v 输出传递给JVM的参数
jstack(JVM线程信息监控)
使用场景: 查看JVM线程信息 和生成线程快照。jstack pid 主要用于生成指定进程当前时刻的线程快照,线程快照是当前java虚拟机每一条线程正在执行的方法堆栈的集合。分析线程栈
Jmap(JVM内存占用信息和快照)
使用场景: 监控堆内存使用情况和对象占用情况, 生成堆内存快照文件,查看堆内存区域配置信息。**jmap **打印指定java进程的共享对象内存映射或堆内存细节。堆Dump是反映堆使用情况的内存镜像,其中主要包括系统信息、虚拟机属性、完整的线程Dump、所有类和对象的状态等。
**jmap pid **共享对象的起始地址、映射大小、共享对象路径的全程。 jmap -heap pid:查看堆使用情况jmap -histo pid:查看堆中对象数量和大小
Jstat (JVM内存信息统计)
使用场景 :用于查看各个功能和区域的统计信息(如:类加载、编译相关信息统计,各个内存区域GC概况和统计)jstat-gc pid: 统计垃圾回收堆的行为
Jinfo(JVM参数查看和修改)
使用场景: 查看和调整JVM启动和运行参数。
Jinfo pid 查看JVM整个系统参数信息jinfo -flag [参数名] pid 查看某个具体参数jinfo -flag启动某个配置
java查询JVM配置参数
查询JVM配置参数java -XX:+PrintCommandLineFlags
C:\Program Files\Java\jdk1.8.0_91\bin>java -XX:+PrintCommandLineFlags-XX:InitialHeapSize=199690240 //初始堆大小bytes 这里23M-XX:MaxHeapSize=3195043840 //最大堆大小bytes 这里380M-XX:+PrintCommandLineFlags //PrintCommandLineFlags 是打印那些被新值覆盖的项-XX:+UseCompressedClassPointers //UseCompressedClassPointers:类指针压缩-XX:+UseCompressedOops //UseCompressedOops:普通对象指针压缩-XX:-UseLargePagesIndividualAllocation //关闭减少处理器 TLB 缓存压力的技术-XX:+UseParallelGC //设置并行收集器 “Parallel Scavenge” + "Parallel Old"组合
查询JVM配置参数java -XX:+PrintFlagsFinal -version |FINDSTR /i “:”
C:\Program Files\Java\jdk1.8.0_91\bin>java -XX:+PrintFlagsFinal -version |FINDSTR /i ":" intx CICompilerCount := 3 {product} uintx InitialHeapSize := 201326592 //初始堆大小bytes {product} uintx MaxHeapSize := 3196059648 //最大堆大小bytes {product} uintx MaxNewSize := 1065353216 //新生代分配内存最大上限,小于-Xmx的值; {product} uintx MinHeapDeltaBytes := 524288 //要扩容或者缩容最小扩/缩多少 {product} uintx NewSize := 67108864 //新生代初始内存的大小,应该小于-Xms的值; {product} uintx OldSize := 134217728 //老年代的默认大小 {product} bool PrintFlagsFinal := true //打印所有的默认参数设置 {product} bool UseCompressedClassPointers := true {lp64_product} bool UseCompressedOops := true {lp64_product} bool UseLargePagesIndividualAllocation := false {pd product} bool UseParallelGC := true {product}java version "1.8.0_91"Java(TM) SE Runtime Environment (build 1.8.0_91-b14)Java HotSpot(TM) 64-Bit Server VM (build 25.91-b14, mixed mode)
配置Windows JVM参数
1、系统环境中配置(推荐)
虚拟机内存的大小除了在web容器中设置,我们还可以通过系统环境变量来设置,下面看看设置步骤: 打开windows系统环境变量,在系统变量中,新建变量JAVA_OPTS,值设置为:
8G物理内存JVM虚拟机配置idea优化命令-XX:+UseG1GC -XX:+UseStringDeduplication -XX:MaxGCPauseMillis=95 -Xms5120m -Xmx5120m -Xmn1024m -Xss128k -XX:MaxTenuringThreshold=0jdk8 使用G1垃圾回收器-XX:-UseParallelGC -Xms3550m -Xmx3550m -Xmn1024m -Xss128k -XX:+UseG1GC -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication -XX:MaxGCPauseMillis=95 -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MatespaceSize=6
优化前启动优化前jmeter测试
优化后启动优化后jmeter测试
jvm中常用的参数含义:
每个对象都有一个计数器,每次YGC 都会加1,配置计数器的值到达某个阐值的时候, 对象从 新生代晋升至老年。 -XX:MaxTenuringThreshold
为功能点比较多,在运行过程中,要不断动态加载很多的类,经常出现致命错误。为了解决该问题, 需要设定运行参数 -XX: MaxPermSize= 1280m ,
以给NM 设置运行参数让JVM 遇到OOM 异常时能输出堆内信息。 -XX:+HeapDumpOnOutOfMemoryError
1: -Xmx指定 jvm 的最大内存大小 , 如 :-Xmx=2048M(根据设备物理内存以及实际情况设定,建议为物理内存的80%) 2: -Xms指定 jvm 的初始内存大小 , 如 :-Xms=2048M, 高并发应用, 建议和-Xmx一样, 防止因为内存收缩/突然增大带来的性能影响. 3: -Xmn指定 jvm 中 New Generation (堆空间的新生代空间)的大小 , 如 :-Xmn=256m。 这个参数很影响性能, 如果你的程序需要比较多的临时内存, 建议设置到512M, 如果用的少, 尽量降低这个数值, 一般来说128/256足以使用了。 4: -XX:PermSize (java7,java8移除)指定 jvm 中 Perm Generation (永久存储区)的最小值 , 如 :-XX:PermSize=32m。 这个参数需要看你的实际情况。可以通过jmap 命令看看到底需要多少。 5: -XX:MaxPermSize(java7,java8移除)指定 Perm Generation 的最大值 , 如 :-XX:MaxPermSize=64m 6: -Xss指定线程桟大小 , 如 :-Xss=128k, 一般来说,webx框架下的应用需要256K。 如果程序中有大规模的递归行为,请考虑设置到512K/1M。 这个需要全面的测试才能知道。 不过,256K已经很大了。 这个参数对性能的影响比较大的。 7:-XX:MatespaceSize(java8)和-XX:MatespaceSize(java8)JVM加载类的时候,需要记录类的元数据,这些数据会保存在一个单独的内存区域内,在Java 7里,这个空间被称为永久代(Permgen),在Java 8里,使用元空间(Metaspace)代替了永久代。由于调整元空间的大小需要Full GC,这是非常昂贵的操作,如果应用在启动的时候发生大量Full GC,通常都是由于永久代或元空间发生了大小调整,基于这种情况一般建议在JVM参数中将MetaspaceSize和MaxMetaspaceSize设置成一样的值,并设置得比初始值要大,对于8G物理内存的机器来说,一般我会将这两个值都设置为512M。
2、使用命令配置
java命令配置
8G物理内存JVM虚拟机配置java -XX:+UseG1GC-Xms3550m -Xmx3550m -Xmn1024m -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MatespaceSize=512m -XX:MaxMetaspaceSize=512m -XX:MaxTenuringThreshold=0
使用 -Xms 设置堆的初始空间大小 java -Xms20m -Xmx30m GCDemo
JVM 提供了参数 -Xmn 来设置年轻代内存的大小 java -Xms20m -Xmn10M GCDemo
使用 -XX:SurvivorRatio 这个参数,该参数设置 eden / from 空间的比例关系 -XX:SurvivorRatio = eden/from = eden/to java -Xms20m -Xmn10M -XX:SurvivorRatio=2 -XX:+PrintGCDetails GCDemo
永久代(JDK1.7)所加载的类信息都放在永久代中。用 -XX:PermSize 设置永久代初始大小,用 -XX:MaxPermSize 设置永久代最大大小。 java -XX:PermSize=10m -XX:MaxPermSize=50m -XX:+PrintGCDetails GCDemo
元空间(JDK1.8)在 JDK1.8 之时,永久代被移除,取而代之的是元空间 java -XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=50m -XX:+PrintGCDetails GCDemo
栈空间是每个线程各自有的一块区域,如果栈空间太小,也会导致 StackOverFlow 异常。而要设置栈空间大小,只需要使用 -Xss 参数就可以。 java -Xss2m GCDemo
在 JVM 中还有一块内存,它独立于 JVM 的堆内存,它就是:直接内存。 java -XX:MaxDirectMemorySize=50m GCDemo
实时修改JVM参数:jinfo -flag name = value PID 如果要对参数进行实时调整:则需要看到参数后面有manageable的才能被实时调整
9.4 Linux JVM调优
基本同windows,只是命令上大同小异。 使用命令配置
8G物理内存JVM虚拟机配置java -XX:+UseG1GC-Xms3550m -Xmx3550m -Xmn1024m -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MatespaceSize=512m -XX:MaxMetaspaceSize=512m -XX:MaxTenuringThreshold=0
参考链接
jmeter
https://cloud.tencent.com/developer/article/1633626 https://blog.csdn.net/wust_lh/article/details/86095924 https://blog.csdn.net/qq_37453279/article/details/107990659 https://zhuanlan.zhihu.com/p/142897766
获取jvm日志
https://blog.csdn.net/zlzlei/article/details/46471627 https://blog.csdn.net/S1124654/article/details/125467265 https://www.jianshu.com/p/0167a0fc8063 [https://zhuanlan.zhihu.com/p/355765061[https://blog.csdn.net/qq_35925558/article/details/116464460
jvm监控调优关注参数指标
[https://blog.csdn.net/weixin_41605937/article/details/121704836https://blog.csdn.net/weixin_43935927/article/details/109233111 [https://zhuanlan.zhihu.com/p/269597178[https://zhuanlan.zhihu.com/p/267381560
jvm调优
https://blog.csdn.net/augsm/article/details/109272205 https://tianweichang.blog.csdn.net/article/details/109712806 https://heapdump.cn/ https://mp.weixin.qq.com/s?__biz=MzkwNjMwMTgzMQ==&mid=2247495919&idx=1&sn=71010d91e376270afc31bbe61c8326aa&chksm=c0e82807f79fa111d7c339832f48c9542d5fc1540c1a619c1a3281040fc1631616e016d0dc36&mpshare=1&scene=23&srcid=0630pKVRvfxq3GMy1Oa2Wxda&sharer_sharetime=1656582521218&sharer_shareid=4b447a3cb6ab5d3443a5fc9771951705#rd https://www.cnblogs.com/z-sm/p/6745375.html https://www.cnblogs.com/zhi-leaf/p/10629033.html https://blog.csdn.net/weixin_43474695/article/details/108248756
https://blog.csdn.net/weixin_28864057/article/details/119661743 https://blog.csdn.net/qq_40902067/article/details/106003880
idea中设置JVM参数
https://zhuanlan.zhihu.com/p/117627812
Java自定义类加载器
https://blog.csdn.net/weixin_42759726/article/details/114030153
查询JVM配置参数分析参考
https://blog.csdn.net/m0_45406092/article/details/110766297 https://www.cnblogs.com/milton/p/6134251.html https://blog.csdn.net/qq13933506749/article/details/120187991 https://www.cnblogs.com/yidaixiaohui/p/10216180.html
JVM关键参数
https://www.cnblogs.com/bapiera/p/13592525.html https://www.cnblogs.com/GtShare/p/9767768.html https://jishuin.proginn.com/p/763bfbd66a1c https://blog.csdn.net/a469517790/article/details/104916916 https://blog.csdn.net/a469517790/article/details/104916916 https://blog.csdn.net/m0_45406092/article/details/110766297
JVM参数之堆栈空间配置
https://blog.csdn.net/qq_40902067/article/details/106003880 https://blog.csdn.net/weixin_28864057/article/details/119661743
JDK8使用G1无效
https://blog.csdn.net/weixin_42629445/article/details/120717860 https://bbs.huaweicloud.com/blogs/247828 https://www.jianshu.com/p/7dd309cc3442 https://www.cnblogs.com/frankyou/p/15048531.html https://blog.csdn.net/Megustas_JJC/article/details/105470675 https://zhuanlan.zhihu.com/p/458098236
java程序输出jvm参数
https://blog.csdn.net/sjl110/article/details/41516745
JDK1.8默认垃圾回收器
https://blog.csdn.net/qq_27500493/article/details/108063108
JVM垃圾收集器【Serial、ParNew、PS、CMS、Serial Old、PO、G1】总结
https://blog.csdn.net/qq_43661709/article/details/122793803
windows配置jVM
https://blog.csdn.net/qq_38776582/article/details/109738067 https://blog.csdn.net/mhqyr422/article/details/79691042
标签:
相关推荐:
精彩放送:
- []在哪里看股指期货的行情?股指期货行情信息
- []当前动态:基金定投可以随时取出来吗
- []Java进阶1-JVM虚拟机 JVM在字节码上的使用方法
- []5.0以下的主流图片加载框架有哪些?安卓加载图片四大框架
- []环球微头条丨如何使用视频剪辑软件将qsv格式视频转换为MP4格式?方法步骤
- []环球今日报丨中国“北斗”卫星导航系统——定位模块需求介绍
- []如何利用大数据实现精准营销?会员管理中用户数据的流转及应用逻辑
- []世界快看:操作系统中死锁的算法——银行家算法
- []当前资讯!DirectSound能帮我们做什么?DirectSound开发指南
- []“流氓”刘邦战胜英雄项羽的因素有哪些?详情介绍
- []当前热门:【干货】Python与STAT时间日期转换问题
- []全球热议:广西提高服务贸易水平 推动优质桂品“出海”
- []天天精选!iOS13越狱教程:如何安装AppSync和afc2补丁?
- []全球观速讯丨st股票什么股
- []股票开户需要多少钱
- []海昌海洋公园2022年营收同比下降近七成,将持续发展顶流IP
- []链家将27座城市转为加盟模式?贝壳:消息不实,仅为小范围合伙人模式
- []当前速讯:美达股份:公司生产的部分产品可在军民融合领域进行应用,具体请以公司公告和定期报告为准
- []每日看点!国睿科技:中国的城市轨道交通全自动运行(无人驾驶)信号系统处于国际先进水平
- []【全球报资讯】悦榕集团2022财年总计63家酒店收官 计划2025年扩张至113家
- []全球看热讯:我爱我家副总裁何洋辞任
- []我爱我家:五八有限公司拟减持不超过2.74%股份 持股比例将低于5%
- []中国恒大披露重组进展
- []电科院:公司具体经营情况详见以往定期报告
- []焦点讯息:航班老是临时取消?民航局要出手了
- []环球新资讯:国泰君安医药一季报业绩前瞻:业绩复苏环比趋势明确
- []【速看料】中信建投:TOPCon电池、组件超额利润有望扩大
- []眼看AI主题基金起高楼 “消费选手”仍在默默坚守
- []天天亮点!AI+元宇宙!Meta离梦想更进一步?
- []苏州常熟2宗宅地将于5月5日出让 起价合计5.4亿元
- []昭衍新药:公司会紧跟行业技术的发展变化,学习和借鉴相关技术在安评业务中的运用
- []环球百事通!中南建设前3月合同销售额120.4亿元 同比减少26.2%
- []消息!南昌中溢置业将转让杭州通原地产40%股权 底价8031.3万元
- []亚通精工:公司未有应披露而未披露事项,股价涨跌受多种因素影响,股价波动是正常的市场交易行为
- []西安国际港务区挂牌2宗宅地面积共117亩 起始总价为7.894亿元
- []财面儿丨越秀地产1-3月累计合同销售额约人民币438.33亿元 同比上升约217.3%
- []当前视点!海容冷链:公司产品不应用于殡葬行业,公司产品应用于快速消费品行业的渠道建设
- []每日时讯!将优化调整高校两成左右学科专业布点
- []【全球报资讯】合肥放开部分区域限购! 多孩家庭可买第3套住房
- []世界今日讯!链家欲在北京、上海以外城市转为加盟模式?贝壳回应:无此计划
- []每经热评|当前并非出台房产税政策的好时机
- []天天讯息:一个月的宝宝很容易被惊吓怎么办_一个月的宝宝发育指标
- []【热闻】怎样取公积金
- []今日热门!怎么取公积金
- []天天快看:交强险怎么用
- []贝壳:链家将27座城市转为加盟模式消息不实 仅为小范围合伙人模式
- []当前消息!滕哈赫:现在才是赛季真正的开始,输给纽卡后我们要有积极回应
- []道达尔能源与伊拉克政府就100亿美元天然气开发项目达成一致
- []世界快资讯丨林斌辞任奥园美谷财务总监职务?江永标继任
- []中南建设:中南城投减持212.03万股 占所持股比例0.11%
- []天天百事通!中南建设前三月累计合同销售金额120.4亿元 同比降26.2%
- []胡泊、李强分别辞任南国置业联席总经理、副总经理
- []万达投资新增质押1930万股万达电影 累计质押6665万股
- []环球今头条!刘鑫获任荣盛发展副总裁
- []全球热文:厦门象屿与河南能源集团签订战略合作协议
- []环球最新:4月05日20时青海海东今天新增确诊名单 4月05日20时青海海东疫情防控政策最新通知
- []当前视点!一半乡土质朴,一半文艺先锋,沙漠河流共生的小城,最美季节到了
- []全球热门:户用储能系统有什么用,有哪些特点和应用?
- []全球看热讯:长久物流设立储能全资子公司!
- []天天亮点!不低于1GW!泰达股份联手千泉实业投建光伏项目
- []30万吨光伏玻璃硅砂提纯项目环评
- []天天视点!超10GW!TCL中环单月出货新突破
- []一彬科技:公司生产经营一切正常。公司对未来汽车产业的发展充满信心
- []国际油价小跌,受制于美国制造业降温,本周重头戏待上演
- []焦点要闻:深圳到九江火车时刻表查询_南昌到九江火车时刻表
- []医道彤行,厚积薄发|2021道彤投资年度合伙人大会特写
- []海淘的childlife大瓶钙含防腐剂?专家建议婴幼儿产品选购要谨慎
- []好好香锅公司怎么样
- []观察:鸿路钢构:钢结构是绿色节能产品,是国家提倡并大力推广的装配式建筑的重要组成部分
- []基金经理猛追AI 但斌却突然唱空:一旦被套 不知猴年马月解套
- []关注:难道是真的?青海发现形状怪异的遗骸,揭开大禹治水背后的真相!
- []世界微头条丨维宏股份:整个Phoenix平台包含了软件和硬件两个部分
- []简讯:拜登:人工智能是否危险还有待观察 但科技公司需为安全负责
- []世界聚焦:2023年Q1季度精选文章合集 | 商旅会奖赛道
- []观速讯丨申请破产!暴跌90%
- []【全球新要闻】2023年Q1季度精选文章合集 | 在线旅游/分销赛道
- []每日关注!四川宜宾:住房公积金最高贷款额度可达90万元
- []全球快讯:伊戈尔:公司会根据客户需求和业务开拓的情况提前布局或者调整相应的产能
- []越秀地产:一季度累计销售约438亿元
- []环球今日讯!合肥调整购房政策:部分区域放开限购
- []全球微资讯!全国春风地图出炉 看看你那儿的四月天
- []环球关注:黄金大涨近2% 逼近历史最高纪录!金价为何持续大涨?专家解读
- []当前快报:是否想念篮球?维金斯:我非常想念队友们 期待与他们并肩作战
- []外汇交易提醒:降息预期升温,美元跌创近两个月新低,新西兰联储决议来袭,纽元续涨有望
- []周鸿祎突然离婚,要AI不要爱?董秘回应来了
- []accountnumber怎么读_Accountnumber
- []4月5日财经早餐:美数据疲软强化美联储放缓加息押注,金价站上2000美元/盎司大关创三十二个月新高
- []【世界聚看点】高达65%成本节约 施耐德电气适配改造服务助企业把握“循环”机遇
- []银行信贷投放不足原因_银行信贷的作用
- []恒达集团控股2022年收入增加约3.4% 纯利减74.3%至7780万
- []环球速读:车险佣金
- []看热讯:三大保险
- []热讯:寿险功用
- []当前资讯!聚焦中概 | 小鹏汽车跌幅扩大至7% 造车新势力普跌
- []双十原则
- []当前快看:乌龟冬眠是为了放水还是放沙?
- []天天快消息!周鸿祎与胡欢离婚 后者分得三六零4.46亿股、对应市值近90亿元
- []环球观热点:周度经济观察:斜率放缓的经济复苏
- []世界观焦点:申通快递:公司与阿里云合作,通过引入云原生技术实现了技术全面升级
- []全球短讯!深交所、沪交所4月8日全面实行注册制交易业务通关测试
- B站注册资本增幅400%至5亿 目前由陈睿全资持股
- 光源资本出任独家财务顾问 沐曦集成电路10亿元A轮融资宣告完成
- 巨轮智能2021年上半年营收11.24亿元 期内研发费用投入增长19.05%
- 红枣期货尾盘拉升大涨近6% 目前红枣市场总库存约30万吨
- 嘉银金科发布2021年Q2财报 期内净利润达1.27亿元同比增长208%
- 成都银行2021上半年净利33.89亿元 期内实现营收同比增长17.27亿元
- 汽车之家发布2021年第二季度业绩 期内新能源汽车品牌收入增长238%
- 中信银行上半年实现净利润290.31亿元 期末不良贷款余额706.82亿元
- 光伏概念掀起涨停潮交易价格创新高 全天成交额达1.29亿元
- 上半年生物药大增45% 关键财务指标好转营收账款持续下降
- 亚太药业向下修正可转债价格 律师:索赔宜趁早
- 假期安全注意事项内容图片_假期安全注意事项内容
- 香山股份:目前尚无详细的市场份额数据,更多详情敬请留意公司官网及相关公告和定期报告
- 全球快看:秦安股份:4月3日公司高管刘宏庆减持公司股份合计1.16万股
- 保利发展:房地产持续向好的基本面没有变
- 世界快资讯:越秀地产前三月销售438亿?同比上升217%
- 当前聚焦:格力地产:珠海国资委同意公司收购免税集团 并募资不超70亿元
- 天天观点:保利发展:公司负债率连续三年下降 继续保持稳健财务政策
- 保利发展:灵活安排推货节奏?把握市场修复窗口
- 今日要闻!国家加强铁矿石价格形势分析研判和期现货市场监管
- 世界热资讯!宝馨科技:目前公司怀远一期2GW异质结电池及组件项目正在加速推进中,预计年内投产
- 天天观点:中交城投郑州古荥城更项目获得首笔融资
- 岭南股份:公有云是云计算的主要形态。公司已与腾讯建立云计算、数字虚拟人、大数据等方面的战略合作
- 世界短讯!西安土拍市场“活”了?
- 世界快报:湖北襄阳高新区2.08亿售出65亩宅地 竞得者为本地房企
- 今日热讯:协创数据:公司存储设备主要与联想集团合作
- 【全球播资讯】三代人七十余载接力守护156座抗美援朝烈士墓
- 全球观天下!每日互动:AIGC和ChatGPT都是融合多种AI技术的成果
- 天天滚动:神州高铁:截至2023年3月31日,公司股东人数为91207
- 【天天新要闻】昭衍新药:股价走势受多方面因素的影响,还请谨慎投资
- 世界滚动:财面儿丨建发国际:前3月权益销售额353.4亿元,同比增长63.5%
- 全球实时:土地注册处:香港3月楼宇买卖合约8599份 按年升124.6%
- 【天天新要闻】昆明公租房开发公司最终发行6亿 品种一利率6.5%、品种二未发行
- 全球观点:拼多多升级组织架构 联合创始人赵佳臻出任联席CEO搭档陈磊
- 上海3月新建商品住宅成交面积环比增长94% 均价下跌2.8%
- 天天最资讯丨迪马股份为江苏2家子公司提供融资担保 涉资8.04亿元
- 滚动:狂飙910%!德国大储市场崛起,户储地位岌岌可危?
- 新消息丨最新进展!中科云网5GW TOPCON电池项目一期签署建设施工合同
- 焦点信息:煤矸石综合利用与矿山生态修复的战略思考
- 环球观热点:年产500万吨!全球规模最大光伏砂项目成功签约
- 最大涉水750mm 北京越野BJ60新增车型上市售24.58万-27.68万元
- 【天天播资讯】晶硅组件有什么作用和特点,有哪些种类?
- 环球旅讯+WiT新加坡主题沙龙开场演讲:你好,中国!
- 天天报道:新地University Hill料最快4月底开售
- 环球速递!万通发展:万通控股解质押270万股股份 现持公司股份3.34亿股
- 全球微动态丨建发房地产:10亿元公司债券票面利率为4.25%
- 世界头条:中核钛白:公司第三期员工持股计划并未在2023年3月14日进行大宗交易
- 全球观速讯丨祥生控股首季销售额54.19亿元 同比下滑38.73%
- 国际油价走强,但多头须警惕OPEC+最新减产的潜在负效用
- 恒基达鑫:公司始终密切关注横琴粤澳深度合作区相关的措施和政策情况,望能充分利用和享受到政策带来的红利
- 当前滚动:顾家家居:截至3月末累计回购股份106.28万股 总代价4187.73万元
- 海新能科: 截至2023年03月31日,公司股东总人数为45,272名
- 中红医疗:我国丁腈手套产品与马来西亚相比有一定的成本优势
- 经纬辉开:副董事长拟减持公司不超0.39%股份
- 富力地产:2022年度净亏损157.79亿元 预计今年可售货值超1250亿元
- 全球热点!小摩增持万物云39.86万股 总金额约1406.76万港元
- 全球速讯:嵘泰股份:我公司上市公司同行有旭升集团、爱柯迪、文灿股份等
- 新大正:正积极推进收购云南沧恒投资80%股权 尚存在不确定性
- 环球要闻:航天发展:截至2023年3月31日,航天发展股东户数为179,101户
- 当前快播:NYMEX原油仍上看83.17美元
- 4月4日福晶科技涨停分析:3D感应,中科院系,光通信概念热股
- 会德丰合作盘MIAMI QUAY I暂累售49伙 套现4.8亿港元
- 环球速读:“20绿城03”将于4月13日提前摘牌 发行金额为10亿元
- 天天资讯:4月4日中储股份涨停分析:央企改革,快递物流,国企改革概念热股
- 4月4日四川黄金涨停分析:黄金概念热股
- 环球今日讯!信达证券发布金陵饭店研报 年报点评:全年业绩稳中有增 布局中高端 注重品牌打造
- 焦点!学习心得怎么写?学习心得范本?
- 怎样追女生?追女孩子的方法有哪些?
- 环球观热点:仙剑奇侠传3有哪些歌曲?仙剑奇侠传3所有歌曲汇总?
- 合山市景点有哪些?合山市景点介绍?
- 每日短讯:降雨量50毫米是怎么计算的?降雨量50毫米的计算方法?
- 当前资讯!生物圈2号为什么会失败?生物圈二号失败的重要原因?
- 中青旅2022年营收64.17亿元,旅行社业务亏损收窄
- 捷信金融怎样贷款?捷信金融贷款条件有哪些?
- 环球热议:lol英雄联盟怎么观战?观看别人的游戏战斗方法?
- 每日看点!速干衣的特点有哪些?速干衣的主要功能是什么?
- 速讯:and1鞋子怎么样?and1鞋子有哪些特点?
- 焦点简讯:北京:加大老旧平房院落、老旧小区、危旧楼房和简易楼等更新力度
- 世界热文:常青股份:年报审计工作正在进行中,年报将于2023年4月26日披露
- 天天最新:山西大同:住房公积金贷款最高额度提至100万元
- 环球今头条!国际金价跌势受限,美国数据再现疲软,FED鹰派呼声难响
- 美原油交易策略:需求预期接力,油价或延续涨势
- 环球新消息丨苏泊尔拟分红24.40亿元 控股股东SEB国际或分得20.12亿元
- 千方科技:公司未参与您所提及的业务
- 当前快播:河南新乡:住房公积金最高贷款额度升至65万元
- 全球速读:发改委:产业目录引导横琴加大对新兴产业等的培育
- 焦点消息!年报横评①| 这些物企表现最好!五大指标透视2022年指标之最
- 世界焦点!医贝云服销售总监陈小飞:医贝云服伴随着药品和耗材供应链改革而诞生
- 孕妇补钙用金丐,早吃早手艺
- 环球新资讯:甘化科工:截至2023年3月31日,公司股东人数为27,947户
- 天天动态:上海新华联国际独栋商墅第三次流拍 起始价1.29亿元
- 焦点精选!明阳智能:尊敬的公司公司对外信息披露均按照信息披露要求进行
- 环球时讯:德恩精工子公司拟与亿盛房地产合作开发“滨江一号”项目 预计总投资约1.4亿元
- 环球今日讯!二手房成交量“狂飙”,百城落地“带押过户”
- 环球焦点!国际金价短线下看1970美元
- 【天天热闻】上海钢联:根据创业板上市公司相关规则,创业板上市公司无需披露季度业绩预告
- 非凡舞蹈学院创办人Jamila 王海青,打破自我,永不设限!善济有约
- 股票进仓是什么意思
- 云南省餐饮行业协会交流座谈会在文山举行
- “AI”拼才会赢?16只基金单日飙涨超7% 公募基金开始密集大调仓
- 三围怎么量
- 当前焦点!炒外汇为什么要拉人
- 用了“借钱三巨头”之一的钱小乐,真实感受:靠谱!
- 手机炒股票用什么软件最好
- 全球信息:收购瑞信后 瑞银将取代摩根大通成为拉美最大财富管理公司
- 市场对黄金ETF和金币的兴趣激增,渣打称这还只是开始!
- 天天热点!现货黄金交易策略:美元仍存下行风险,金价或震荡上攻
- 对冲基金放弃看空押注,金银正蓄势待涨!
- 当前播报:长春城投10亿元私募债券项目状态更新为“已反馈”
- 全球看点:北京:土地出让收入用于农业农村比例不低于7.5%