JVM入门
JVM概述
JVM位置
JVM体系结构
注意:栈中一定不存在垃圾,栈中数据用完一个弹出一个,总结来说,栈区、本地方法栈、程序计数器这三块必定不存在垃圾。JVM调优主要是针对方法区、堆(99%)进行调优。
常用的第三方插件(如Lombok)都是操作执行引擎区域,生成对应getter、setter方法
- 本地方法栈,例如Thread类中的start0()方法。凡是native修饰的方法,说明Java作用范围达不到,需要调用底层C语言的库,会进入到本地方法栈,进而调用本地方法接口JNI
JNI的作用是:扩展Java的使用,融合不同的编程语言为Java所用
JVM单独在内存区域中开辟一块标记区域:Native Method Stack,登记native方法(仅登记,并不执行),最终执行的时候,通过JNI加载本地方法库的方法 - PC寄存器
每个线程都有一个程序计数器,是线程私有的,就是一个指针,在执行引擎读取下一条指令 - 方法区(本质也属于堆)
被所有线程共享,所有字段和方法字节码、一些特殊方法,如构造函数,接口代码也在此定义。简单说,所有定义的方法信息都保存在此区域,此区域为共享区间。
注意:静态变量(static)、常量(final)、类信息Class模板(构造方法、接口定义)、运行时的常量池存在方法区中,但是,实例变量存在堆内存中,与方法区无关 - Java栈,详见3
- 堆,详见4
- 线程私有:Java栈、程序计数器、本地方法栈
- 线程共享:方法区、堆
类装载器
类装载过程
Java中所有类,都需要由类加载器装载到JVM中才能运行。类加载器本身也是一个类,其作用是:将class文件从硬盘读取到内存中
类加载方式有两种:
- 隐式装载:程序运行中碰到new等方式创建对象时,隐式调用类装载器加载到对应的类到JVM中
- 显式装载:通过class.forname()等方法,显式加载
备注:Java的加载是动态的,并不会一次性加载所有类后才运行,而是保证运行的基础类完全加载到JVM中,其他类只有在需要的时候才加载,为了节省内存开销
类装载执行过程:
- 加载:根据查找路径找到对应的class文件后导入
- 验证:检查加载的class文件的正确性
- 准备:给类中的静态变量分配内存空间
- 解析:虚拟机将常量池中的符号引用替换为直接引用的过程。
符号引用——可理解为一个标识;直接引用——直接指向内存中的地址 - 初始化:对静态变量和静态代码块进行初始化工作
类加载器分类
定义:实现通过类的全限定名获取该类的二进制字节流的代码块
分类:
- 启动类加载器(Bootstrap ClassLoader):加载Java核心类库,无法被Java程序直接引用;是虚拟机的一部分,用来加载Java_HOME/lib目录下的类库
- 扩展类加载器(ExtClassLoader):加载Java扩展库。负责加载\lib\ext目录的所有类库
- 系统类加载器(AppClassLoader):位于jre环境下的rt.jar内,根据Java应用的类路径(classpath)加载Java类,基本上我们创建的类都是它完成加载,可通过ClassLoader.getSystemClassLoader()获取该类加载器
- 用户自定义类加载器:通过继承java.lang.ClassLoader类的方式实现。
public class Car {public static void main(String[] args) {Car car1 = new Car();Car car2 = new Car();Class<? extends Car> aClass = car1.getClass();Class<? extends Car> bClass = car1.getClass();// 输出一致,说明两个实例由一个Class模板实例出System.out.println(aClass.hashCode());System.out.println(bClass.hashCode());ClassLoader classLoader = aClass.getClassLoader();ClassLoader classLoader2 = classLoader.getParent();ClassLoader classLoader3 = classLoader2.getParent();// AppClassLoaderSystem.out.println(classLoader);// ExtClassLoaderSystem.out.println(classLoader2);// null(Java程序读取不到,Java早期由C,C++语言编写,去除了C++中 指针和内存管理,所以早期也叫C++--)System.out.println(classLoader3);}
}5592464
5592464
sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@424c0bc4
null
双亲委派机制
重新定义一个java.lang.String类,启动时报错“无法找到main方法”
解释:最终会通过“Bootstrap ClassLoader”加载器找到 “rt.jar”包下的“java.lang.String”类,所以不会加载到自定义的String.java
出现这种情况是由于类加载器的“双亲委派机制”
定义:如果一个类加载器收到了类加载的请求,它首先不会自己去加载该类,而是把请求委派给父类加载器,每一层都是如此,这样所有加载请求都会被传送到顶层的启动类加载器中,只有当父加载器无法完成加载请求时,抛出异常通知子加载器尝试加载
这样设计的目的是:为了安全,防止开发人员修改一些系统类。
简单理解:当一个类收到类加载请求时,不会自己去加载,而是将其委派给父类,如果父类不能加载,再交由子类去完成加载
沙箱安全机制(非重点)
Java安全模型核心就是Java沙箱(sandbox),所谓沙箱机制,就是将Java代码限定在虚拟机(JVM)特定运行环境中,并严格限制代码对本地系统资源访问。通过这种保护措施保护代码的有效隔离,防止对本地系统造成破坏。
沙箱主要限制系统资源访问,系统资源包括:CPU、内存、文件系统、网络。不同级别的沙箱对资源访问限制也可以不一样
所有Java程序运行都可以指定沙箱,定制安全策略
在Java中将执行程序分为本地代码和远程代码两种,本地代码默认是可信任的,远程代码则被看作是不受信任的。对于授信的本地代码,可以访问一切本地资源,而对于非授信的远程代码,在早期Java实现中,安全依赖于沙箱机制。
但如此严格的安全机制也给程序功能扩展带来障碍,比如当用户希望远程代码访问本地系统的文件时,就无法实现,因此在后续Java1.1版本中,对安全机制做了改进,增加了安全策略,允许用户指定代码对本地资源的访问权限
在jdk1.2版本中,再次改进安全机制,增加了代码签名,无论本地代码还是远程代码,都会按照用户的安全策略设定,由类加载器加载到虚拟机权限不同的运行空间,实现差异化代码执行权限控制
当前最新的安全机制实现,则引入域(Domain)的概念,虚拟机会把所有代码加载到不同系统域和应用域,系统域专门负责与关键资源进行交互,而各应用域部分则通过系统域的部分代理来对各种需要的资源进行访问,虚拟机中不同的受保护域对应不同权限,存在于不同域中的类文件就具有当前域的全部权限
组成沙箱的基本组件:
- 字节码校验器:确保Java类文件的语法规范,可实现内存保护,但并非所有类文件都会经过字节码校验,比如核心类(例如java,javax包下)
- 类装载器:主要有3个方面
- 防止恶意代码干涉善意的代码(双亲委派机制)
- 守护被信任的类库边界
- 将代码归入保护域,确定代码可进行哪些操作
虚拟机为不同类加载器载入的类提供不同的命名空间,命名空间由一系列唯一名称组成,每一个被装载的类将有一个名字,该命名空间由Java虚拟机为每个类装载器维护,他们之间互相不可见
类装载器采用双亲委派机制:
- 由最内层Java自带类装载器开始加载,外层恶意同名类得不到加载而无法使用
- 由于严格通过包区分访问域,外层恶意的类通过内置代码也无法获得权限访问到内层类,破坏代码自然无法生效
- 存取控制器:可以控制核心API对操作系统的存取权限,而这个控制策略设定,可由用户指定
- 安全管理器:核心API和操作系统之间的主要接口,实现权限控制,比存取控制器优先级高
- 安全软件包:java.security下的类和扩展包下的类,允许用户为自己的应用增加新的安全特性,包括:
- 安全提供者
- 消息摘要
- 数字签名(keytools、https)
- 加密
- 鉴别
栈
栈的特点:先进后出(所以main()方法,最先执行,最后结束)
栈:每个线程都有自己的线程栈,主管程序的运行,生命周期和线程同步;线程结束,栈内存释放。故栈中不存在垃圾回收问题!
栈中主要存放:8大基本类型、对象的引用(引用地址)、实例的方法
栈运行原理:每运行一个方法产生一个栈帧。当栈满了就会抛出错误StackOverflowError
JVM版本
三种JVM版本:
- Sun公司 的 HotSpot
HotSpot(TM) 64-Bit Server VM (build 25.112-b15, mixed mode)
- BEA公司 的 JRockit
- IBM公司的 J9VM JIT编辑器
堆
一个JVM只有一个堆内存(垃圾回收基本都在此),堆内存大小是可以调节的。
类加载器读取了类文件后,一般存放 类、方法、常量、变量、以及引用类型的真实对象。
堆内存细分为三个区域:
- 新生区(伊甸园区)
- 老年区(Old)
- 永久区(Perm)
GC垃圾回收,主要发生在新生区和老年区,假若内存满了就会出现OOM异常
注意:
- JDK以后,永久存储区,被称为 元空间
新生区
-
所有对象都是在 伊甸园 区 被new出来
-
假若 伊甸园区 空间达到阈值,触发一次 轻GC,该对象仍存活,就被移到幸存区
-
当新生区内存达到阈值,触发 重GC,存活的对象移到 老年区
-
特点:对象更新速度快,短时间内产生大量的“”死亡对象,产生连续可用的空间,所以使用复制清除算法和并行收集器进行垃圾回收,称为初级回收(minor gc)
-
发展变化:当对象在Eden出生后,经过一次minor GC后,若对象还存活着,并能被另一块survivor区域所容纳,则使用复制算法将其复制到另一块survivor区域,并将该对象年龄+1,当对象年龄达到某个值(默认为15)时,该对象即可变为老年代
老年区
老年代的GC算法采用标记-清除算法
注意:标记-清除算法收集垃圾的时候会产生许多的内存碎片。
永久区
此区域常驻内存的,用于存放JDK自带的class对象,interface元数据,存储的是Java运行时的环境或类信息(此区域不存在垃圾回收,关闭JVM时释放此区域内存)
- 在JDK1.6之前:永久代,常量池是存放在方法区的
- JDK1.7:永久代,但提出
去永久代
的思想,此时常量池存放于 堆 中 - JDK1.8:无永久代,常量池在元空间
查看JVM内存参数:
public class JVMDemo {public static void main(String[] args) {// 虚拟机能使用的最大内存(默认占电脑内存1/4)long max = Runtime.getRuntime().maxMemory();// 单位为字节System.out.println("max内存:"+max+"字节");// JVM初始化总内存(默认占电脑内存1/64)long total = Runtime.getRuntime().totalMemory();// 单位为字节System.out.println("total内存:"+total+"字节");}
}
max内存:3793747968字节
total内存:257425408字节
调整JVM参数:
-XX:+PrintGCDetails打印GC时内存信息
from、to对应幸存者0、1区(幸存者01区会随时交换位置)
注意:上述堆空间模型分布,逻辑上存在,物理上不存在(从打印结果可看出,PSYoungGen+ParOldGen就等于堆空间,而元空间并未占用堆内存,实际存于本地内存)
查看GC过程
public class JVMDemo {// JVM参数 -Xms8m -Xmx8m -XX:+PrintGCDetailspublic static void main(String[] args) {String str = "khfkoanngopaalknfasopajr";while (true) {str += str + new Random().nextInt(918246192) + new Random().nextInt(189242864);}}
}
JPofiler工具分析OOM原因
当项目出现OOM异常,尝试扩大JVM内存仍无法解决问题时,就需要排查何种原因导致
分析工具有 MAT、JPofiler,作用有:
- 分析Dump内存文件,快速定位内存泄漏
- 获得堆中数据
- 获得大的对象
工具安装:
- IDEA安装plugins:JPofiler
- 安装客户端(安装路径不能有空格、中文)
- IDEA配置JPofiler启动位置
- 在启动类上配置 OOM 时输出dump文件
- 在src目录下找到dump文件,用JPofiler打开
基本信息:
大对象数据:
线程对应异常行:
GC回收
在Java中,开发者无需显式地释放一个对象地内存,而是由虚拟机自动执行。
在JVM中,有一个垃圾回收线程,它是低优先级的,只在虚拟机空闲或堆内存不足时,才会触发执行,扫描没有被任何引用的对象,并将它们添加到要回收的集合中,进行回收
Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的。Java没有提供释放已分配内存的显式操作方法。
GC回收主要针对 堆和方法区(本质也在堆中)
GC回收分为:轻GC、重GC(full-GC)
如何判断对象可被回收
一般有两种办法判断:
- 引用计数器法:为每个对象创建一个引用计数,有对象引用时+1,引用被释放时-1,当计数为0时候表示可被回收。
缺点:无法解决循环引用问题 - 可达性分析算法:从GC Roots开始向下搜索,搜索走过的路径称为引用链,当一个对象到GC Roots没有任何引用链的时候,说明该对象可被回收
GC常见题目:
- JVM内存模型和分区,每个区放什么?
- 堆里面的分区有哪些(Eden、from、to、老年区),并说明其特点
- GC算法有哪些?标记清除法、标记压缩、复制算法、引用计数器,怎么用的?
- 轻GC和重GC,分别在什么时候发生
垃圾回收算法
- 复制算法(主要用于新生区,对象存活率较低):按照容量划分两个大小相等的内存区域,当一块用完的时候将活着的对象复制到另一块中,然后一次性清理掉已使用的内存空间
优点:无内存碎片
缺点:内存使用率只有原来的一半
- 标记-清除算法(mark-sweep):标记无用对象,然后进行清除回收
缺点:两次扫描效率不高,产生大量不连续的垃圾碎片
- 标记-整理算法(常用于老年区):标记无用对象,让所有活着的对象都向一端移动,直接清理掉边界以外的内存
新生代中可以用复制算法,但老年代由于对象存活率高,会有较多的复制操作,导致效率变低,因此出现该算法
缺点:再多一次扫描,仍需要进行局部移动,一定程序降低效率
- 分代收集算法(GC回收使用的算法):根据对象存活周期将内存划分几块,一般是新生代(存活率低)采用复制算法,老年代采用标记-整理算法
内存效率:复制算法>标记-清除>标记-整理
内存整齐度:复制算法=标记-整理>标记-清除
内存利用率:标记-整理=标记-清除>复制算法
调优参数
- -Xms2g:初始化推大小为 2g;
- -Xmx2g:堆最大内存为 2g;
- -XX:NewRatio=4:设置年轻的和老年代的内存比例为 1:4;
- -XX:SurvivorRatio=8:设置新生代 Eden 和 Survivor 比例为 8:2;
- –XX:+UseParNewGC:指定使用 ParNew + Serial Old 垃圾回收器组合;
- -XX:+UseParallelOldGC:指定使用 ParNew + ParNew Old 垃圾回收器组合;
- -XX:+UseConcMarkSweepGC:指定使用 CMS + Serial Old 垃圾回收器组合;
- -XX:+PrintGC:开启打印 gc 信息;
- -XX:+PrintGCDetails:打印 gc 详细信息。‘
JMM(Java Memory Model)
heppen-before机制
相关文章:

JVM入门
JVM概述 JVM位置 JVM体系结构 注意:栈中一定不存在垃圾,栈中数据用完一个弹出一个,总结来说,栈区、本地方法栈、程序计数器这三块必定不存在垃圾。JVM调优主要是针对方法区、堆(99%)进行调优。 常用的第三…...
Cmake基础(5)
这篇文章主要描述如何使用cmake构建一个库工程 文章目录 add_libraryinstall 库工程的代码:头文件和源文件 #ifndef ADD_H #define ADD_H#ifdef _WIN32 #ifdef MYMATH_EXPORTS #define MYMATH_API __declspec(dllexport) #else #define MYMATH_API __declspec(dll…...
Rabbitmq 死信取消超时订单
本文使用的版本 otp_win64_25.0rabbitmq-server-3.11.26rabbitmq插件 rabbitmq_delayed_message_exchange-3.11.1 pom.xml文件 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId> …...
C语言—每日选择题—Day55
指针相关博客 打响指针的第一枪:指针家族-CSDN博客 深入理解:指针变量的解引用 与 加法运算-CSDN博客 第一题 1. 若有如下定义,则 p1&m;p2p1; 是正确赋值语句.说法是否正确? int *p1; int *p2; int m …...

软件测试岗位的简历怎么写?项目怎么包装
已经帮大家打包好了包装好的简历模板,大家可以直接进行套用,详情请望下看 自动化测试相关教程推荐: 2023最新自动化测试自学教程新手小白26天入门最详细教程,目前已有300多人通过学习这套教程入职大厂!!_哔哩哔哩_bili…...

服务器解析漏洞是什么?攻击检测及修复
服务器解析漏洞(Server-side Include Vulnerability,SSI漏洞)是一种安全漏洞,通常出现在支持服务器端包含(SSI)功能的Web服务器上。SSI是一种在Web页面中嵌入动态内容的技术,允许开发人员将外部…...

HTML---CSS美化网页元素
文章目录 前言一、pandas是什么?二、使用步骤 1.引入库2.读入数据总结 一.div 标签: <div>是HTML中的一个常用标签,用于定义HTML文档中的一个区块(或一个容器)。它可以包含其他HTML元素,如文本、图像…...

【Docker】基础篇
文章目录 Docker为什么出现容器和虚拟机关于虚拟机关于Docker二者区别: Docker的基本组成相关概念-镜像,容器,仓库安装Docker卸载docker阿里云镜像加速docker run的原理**为什么容器比虚拟机快**Docker的常用命令1.帮助命令2.镜像相关命令3.容…...

Potplayer播放器远程访问群晖WebDav本地资源【内网穿透】
文章目录 本教程解决的问题是:按照本教程方法操作后,达到的效果是:1 使用环境要求:2 配置webdav3 测试局域网使用potplayer访问webdav3 内网穿透,映射至公网4 使用固定地址在potplayer访问webdav 国内流媒体平台的内容…...
【神经网络】imshow展示图片报错
文章目录 代码示例报错信息报错原因解决方法其他问题 代码示例 plt.imshow(np.squeeze(images[0]))报错信息 Invalid shape (3, 60, 90) for image data报错原因 格式错误,输入具有RGB值的图像,输入三维数组参数的格式应该是(高度…...

【C++】对象特性:无参有参构造函数,拷贝构造函数,析构函数
目录 对象的初始化和清理1.1 构造函数和析构函数1.2 构造函数的分类及调用1.3 拷贝构造函数调用时机1.4 构造函数调用规则1.5 深拷贝与浅拷贝 对象的初始化和清理 生活中我们买的电子产品都基本会有出厂设置,在某一天我们不用时候也会删除一些自己信息数据保证安全。…...

【算法与数据结构】1005、LeetCode K 次取反后最大化的数组和
文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析:本题允许某个下标的数字多次翻转,因此思路比较简单。首先,我们要求最大和&…...

作业--day34
使用select完成TCP并发服务器和客户端 server.c #include <myhead.h>#define PORT 8888 #define IP "192.168.125.137"int main(int argc, const char *argv[]) {int sfd socket(AF_INET, SOCK_STREAM, 0);if(sfd -1){perror("socket error");re…...

车辆违规开启远光灯检测系统:融合YOLO-MS改进YOLOv8
1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 研究背景与意义 随着社会的不断发展和交通工具的普及,车辆违规行为成为了一个严重的问题。其中,车辆违规开启远光灯是一种常见的违规行为,给其…...
爬虫工作量由小到大的思维转变---<第十三章 Scrapy之pipelines分离的思考>
前言: 收到留言: "我的爬取的数据处理有点大,scrapy抓网页挺快,处理数据慢了!" -----针对这位粉丝留言,我只想说:你那培训班老师可能给你漏了课程! 大概你们上课讲的案例属于demo,他教了你一些基本操作,但他没有对相关业务对你讲透! 你研究一下pipelines,或者看我现…...

【Unity】运行时创建曲线(贝塞尔的运用)
[Unity]运行时创建线(贝塞尔的运用) 1. 实现的目标 在运行状态下创建一条可以使用贝塞尔方法实时编辑的网格曲线。 2. 原理介绍 2.1 曲线的创建 unity建立网格曲线可以参考Unity程序化网格体的实现方法。主要分为顶点,三角面,…...

基于DSP的IIR数字滤波器(论文+源码)
1.系统设计 在本次基于DSP的IIR数字低通滤波计中,拟以TMS320F28335来作为系统的主控制器,通过ADC0832模数转换芯片来对输入信号进行采集;通过TLC5615来将低通滤波后的信号进行输出;同时结合MATLAB仿真软件,对设计的II…...

Django(一)
1.web框架底层 1.1 网络通信 注意:局域网 个人一般写程序,想要让别人访问:阿里云、腾讯云。 去云平台租服务器(含公网IP)程序放在云服务器 先以局域网为例 我的电脑【服务端】 import socket# 1.监听本机的IP和…...
微信小程序如何利用createIntersectionObserver实现图片懒加载
微信小程序如何利用createIntersectionObserver实现图片懒加载 节点布局相交状态 API 可用于监听两个或多个组件节点在布局位置上的相交状态。这一组API常常可以用于推断某些节点是否可以被用户看见、有多大比例可以被用户看见。 节点布局相交状态 API中有一个 wx.createInter…...

七:爬虫-数据解析之正则表达式
七:正则表达式概述 正则表达式,又称规则表达式,(Regular Expression,在代码中常简写为regex、regexp或RE),是一种文本模式,包括普通字符(例如,a 到 z 之间的字母…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...

【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...

centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...

如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...