一、jvm简介
1.应用程序申请内存时出现的三种情况:
①OOM:内存溢出,是指应用系统中存在无法回收的内存或使用的内存过多,最终使得程序运行要用到的内存大于能提供的最大内存。此时程序就运行不了,系统会提示内存溢出,有时候会自动关闭软件,重启电脑或者软件后释放掉一部分内存又可以正常运行该软件,而由系统配置、数据流、用户代码等原因而导致的内存溢出错误,即使用户重新执行任务依然无法避免
② Memory Leak:内存泄漏,是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
③内存抖动:指在短时间内有大量的对象被创建或者被回收的现象
黄色模块规定:内存不能超过32G,黄色区域都调用的是jdk底层的内存区域,每个应用模块都占用独立的JVM
2.JVM组成区
流程:首先所有的类文件.class,基于类加载子系统(class loader subsystem)中的类加载器,
将多个类封装继承起来,放到内部来申请内存进行交换;基于类加载子系统在通过执行引擎来处理它的内存空间(runtime data Areas :JVM的内存区域)
执行引擎: 包括JIT (JustInTimeCompiler)即时编译器,动态编译的一个类, GC垃圾回收器
本地方法接口(Native method Interface): 将本地方法栈通过JNI(Java Native Interface)调用Native Method Libraries,比
如C,C++库等,扩展Java功能,融合不同的编程语言为Java所用
3.JVM运行时数据区域
本地方法区method Area(线程共享,JDK8以后叫元空间):线程共享。存放类、常量、静态变量等。
heap (堆):线程共享。堆在虚拟机启动时创建,存放创建的所有对象信息,存放较大资源,具体对象。若对象无法申请将抛OOM异常,通过GC垃圾回收器进行管理。通过-Xmx -Xms 指定最大堆和最小堆空间大小,是JVM内存中最大的区域
Java stack:线程私有,每个线程分配一个栈。存放java8大基本数据类型对象引用,实例的本地变量。
程序计数器(PC寄存器):线程私有,指针,指向某个线程。
本地方法栈:线程私有,非JAVA的一些库。
4.GC垃圾回收器
①引用计数器,引用值为0。(Python) a=100
当pc计数器为0的时候,就清理垃圾
特殊:不会外部程序引用的对象,但不同的方法也在互相引用,这也需被清掉
②Java 根可达算法,找不到的资源为垃圾
5.垃圾回收算法
①:标记清除算法(年轻代)
红色:垃圾 绿色:被使用的内存 灰色:没被使用的内存
弊端:效率高,但是容易出现内存碎片,导致系统内存利用率不高
②:标记压缩算法(老年代)
标记整理法就是将内存中存活的对象往一端移动,然后再将端边界以外的对象清除掉。
③:复制算法(幸存者区)
将内存区域分为两个大小相等的两块,每次只使用其中的一块,当一块用完了之后,便将这块的存活对象复制到另外一块上面,然后一次性将用完的那块 内存数据清除掉。复制算法的过程
优缺点:
效率 复制>清除>压缩
内存整齐度:复制=压缩>清除
内存利用率:压缩=清除>复制
6.jvm垃圾回收详解
STW:stop the world JVM内存回收,垃圾回收时会停止,出现卡顿。
堆内存分代:本地方法区(永久代) 年轻代 老年代
年轻代:伊甸园区(默认8份)(标记清除算法) 幸存区(from---s0 to --- s1) 默认共2份(复制算法)
老年代:默认20份(标记压缩算法)
【注】:幸存者空间,必须留一半空间,用来存放伊甸园区的不是垃圾的数据
总结:起始时。所有新建对象(特大对象直接进入老年代)都出生再eden,启动GC
2:先标记eden存活对象,然后将存活对象复制到s0(假设本次是s0,也可以是s1,它们可以调换),eden剩余所有空间都清空。GC完成
3:继续新建对象,当eden再次满了,启动GC
4:先同时标记eden和s0中存活对象,然后将存活对象复制到s1。将eden和s0清空,此次GC完成
5:继续新建对象,当eden满了,启动GC
6:先标记eden和S1中存活对象,然后将存活对象复制到s0。将eden和s1清空,此次GC完成。
以后就重复上面的步骤
优化参数:
vim /usr/local/tomcat/bin/catalina.sh //编辑配置文件
在空白区域编写 CATALINA_OPTS="-server -Xms1g -Xmx1g "
Xmx **:**堆内存最大使用空间(默认为1/4,最大为默认系统可用内存)
Xms **:**堆内存初始内存(默认为1/64)
【注】:jvm内存建议不要超过32G,否则效率急剧下降
-XX:NewSize 设置新生代大小
-XX:MaxNewSize 设置最大新生代内存大小
-Xmn2g **:**设置年轻代大小为2G。在整个堆内存大小确定的情况下,增大年轻代将会减小老年代,反之亦然。此值关系到JVM垃圾回收,对系统性能影响较大,推荐配置为整个堆大小的3/8。推荐年轻代大小要小于老年代。
-Xss128k **:**设置每个线程的栈大小。默认每个线程栈大小为1M。应当根据应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。需要注意的是:当这个值被设置的较大(例如>2MB)时将会在很大程度上降低系统的性能
-XX:PermSize 非堆内存初始值,默认是物理内存的1/64
-XX:MaxPermSize 最大非堆内存的大小,默认是物理内存的1/4
https://baijiahao.baidu.com/s?id=1681394166244104299&wfr=spider&for=pc
JAVA内存设置
查看java中jvm内存区域的详细大小
java -XX:+PrintGCDetails heap 或者java -Xlog:gc* heap
案例:实现指定jvm堆内存空间、gc垃圾回收过程和OOM错误
javac -cp . heapoom.java
java -Xms100m -Xmx100m -XX:+PrintGCDetails -cp . heapoom
java -Xms500m -Xmx500m -XX:+PrintGCDetails -cp . heap
二、java程序编译
1. maven 部署准备
①:maven 介绍
Maven 翻译为"专家"、"内行",是 Apache 基金会旗下的一个纯 Java 开发的开源项目
Maven 是一个项目管理工具,可以对 Java项目进行构建、解决打包依赖等。
它为开发者提供了一套完整的构建生命周期框架,开发团队稍微投入一些时间就能够自动完成工程的基础构建配置;在有多个开发团队环境的情况下,Maven 能够在很短的时间内使得每项工作都按照标准进行;那是因为大部分的工程配置操作都非常简单并且可复用
Maven基干项目对象模型(POM project object model),它可以通过一小段描述信息(配置)来管理项目的构建;因而,每个maven项目都有一个pom.xml文件
POM( Project Object Model,项目对象模型) 是 Maven 工程的基本工作单元,是一个 XML 文件,包含了项目的基本信息,用于描述项目如何构建,声明项目依赖等,在执行任务或目标时,Maven 会在当前目录中查找 pom 文件,通过读取pom文件获取所需的配置信息,然后执行目标。
pom.xml 文件中可以指定以下配置:
项目依赖
插件
执行目标
项目构建 profile
项目版本
项目开发者列表 相关邮件列表信息
用<packaging> 指定项目打包形式,jar或者war
maven 官网:Maven -- Welcome to Apache Maven
maven 官方仓库 :http://repo.maven.apache.org
maven 下载:
官方 https://maven.apache.org/download.cgi
清华镜像源 http://mirrors.tuna.tsinghua.edu.cn/apache/maven
官方各版本下载地址,推荐使用次新版本 https://archive.apache.org/dist/maven/maven-3
安装maven前必须安装java 环境:
Maven 3.3 要求 JDK 1.7 或以上
Maven 3.2 要求 JDK 1.6 或以上
Maven 3.0/3.1 要求 JDK 1.5 或以上
注意:需要和jdk版本吻合,例如jpress支持jdk1.8
2.maven安装
①安装方式1 :rpm 包安装:yum -y install maven
更改maven配置文件,实现加速
vim /etc/maven/settings.xml
<!--阿里云镜像-->
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>*</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public\</url>
</mirror>
②安装方式2 :二进制安装 Maven -- Installing Apache Maven
3.maven 编译流程:
进入到包含有"pom.xml"的路径,执行
mvn clean install package
有的时候受到测试的干扰,导致无法正在进行编译,这时候可以选择跳过测试,执行
mvn clean install package -Dmaven.test.skip=true
注意:选项"-Dmaven.test.skip=true":跳过测试,并且不编译测试下的源代码
选项"-DskipTests":不执行测试,但是会进行测试代码的编译
如果需要编译的代码很庞大,需要考虑对编译环境做一些处理,提成编译效率:
**启动多线程编译:**mvn -T 4 clean install package -Dmaven.test.skip=true
分配编译的CPU **个数:**mvn -T 2C clean install package -Dmaven.test.skip=true
**启用多线程编译:**mvn clean install package -Dmaven.test.skip=true -Dmaven.compile.fork=true
4.Maven 的打包命令说明:
Maven工程构建的各个环节
clean: 以前编译得到的旧文件class字节码文件删除
compile:将java源程序编译成class字节码文件
test:自动测试,例如,自动调用junit程序
report:报告测试程序执行的结果
package:应用打包,动态Web工程打成war包,java工程打成jar包
install: 是指将打包得到的文件复制到仓库中指定的位置
deploy:将动态Web工程生成的war包复制到Servlet容器下,使其可以运行
5.执行 java 代码编译实战案例
1:编译安装 spring-boot 项目(注意,在pom.xml文件路径下编译
mvn -T 4 clean package -Dmaven.test.skip=true
java -jar spring-boot-helloworld-0.9.0-SNAPSHOT.jar & 运行编译后的java程序
java编译jpress
13157479071 a123456
三、私有仓库 Nexus
1.Nexus简介
Nexus 是一个强大的 Maven 和其它仓库的管理器,它极大地简化了自己内部仓库的维护和外部仓库的
访问。
Nexus 官网:https://www.sonatype.com/
【注】: 安装Nexus建议内存至少4G以上
Nexu监听端口:cat /usr/local/nexus/etc/nexus-default.properties
2.默认仓库有以下 type 类型
Hosted:本地仓库,通常我们会部署自己的构件到这一类型的仓库,比如公司的第三方库
Proxy:代理仓库,它们被用来代理远程的公共仓库,如maven 中央仓库(官方仓库)
Group:仓库组,用来合并多个 hosted/proxy 仓库,当你的项目希望在多个repository 使用资源时就
不需要多次引用了,只需要引用一个 group 即可
仓库配置优化
默认仓库使用国外仓库地址,可修改为国内镜像地址进行加速
可以修改为国内镜像,参考阿里云 仓库服务
配置邮件:参考jumpserver 配置方式
3.使用 Nexus 构建私有 Yum 和 Apt 仓库
通过 Nexus 构建为公司内网 Yum 和 Apt 仓库,代理至阿里云镜像安装包
Rocky-9 :epel-9-Everything-x86_64安装包下载_开源镜像站-阿里云
ubuntu :ubuntu安装包下载_开源镜像站-阿里云
创建仓库blob 存储空间
创建基于blob存储的proxy仓库
在内网测试机上,删除公网路由,重新编写repo文件指向nexus,实现本地repo仓库效果
yum clean all
++[nexus]++
++name=nexus++
++baseurl=http://192.168.10.100:8081/repository/yum-epel-9/++
++gpgcheck=0++
ubuntu仓库模式差不多