
Java内存模型主要包括:线程私有的程序计数器、java虚拟机栈、本地方法栈和线程共享的堆空间、元数据区、直接内存
int a=1;String b="ss";//1和ss便是字面量com.java.Solution类中引用了com.java.Quest,那么com.java.Quest作为符号引用就会存到类常量池,等类加载完,拿着这个引用去元空间找类的内存地址。 try(FileChannel from = new FileInputStream("D:\\asd\\asd.mp4").getChannel();
FileChannel to = new FileOutStream("D:\\asd.mp4").getChannel();){
ByteBuffer bb = ByteBuffer.allocateDirect(1024 * 1024);//读写的缓冲区1Mb,直接内存
while(true){
int len = from.read(bb);
if(len == -1)
break;
bb.flip();
to.write(bb);
bb.clear();
}
}catch(IOException e){
e.printStackTrace();
}
javac:javac是Java编译器,用于将Java源代码编译为字节码文件(.class文件),以便在Java虚拟机上运行。
java:java命令用于启动Java应用程序。它接受字节码文件作为输入,并执行应用程序的入口点(即包含main()方法的类)。
jar:jar命令用于创建和管理Java归档文件(JAR文件),它可以将多个类文件、资源文件和库文件打包到一个JAR文件中,并支持压缩和解压缩操作。
javadoc:javadoc工具用于从Java源代码生成API文档。它读取源代码中的特殊注释(Javadoc注释),并根据注释生成HTML格式的文档,描述类、接口、方法和字段的用法和说明。
jdb:jdb是Java调试器,用于在命令行中调试Java程序。它允许开发人员设置断点、单步执行、查看变量值等,帮助定位和修复代码中的问题。
jconsole:jconsole是一个基于JMX的图形化监控工具,用于监视和管理Java应用程序。它提供了实时的性能指标和线程信息,可用于识别性能问题和调优Java应用程序。
jvisualvm:jvisualvm是一个多功能的Java性能分析工具,提供了各种监控和分析功能。它可以用于查看内存使用情况、线程状态、垃圾回收等,帮助开发人员优化和调试Java应用程序。
jmap:jmap命令用于生成Java堆转储快照(heap dump)文件,以便进行内存分析和查找内存泄漏问题。它可以显示堆内存使用情况、对象实例数量和对象类型等信息。
jps:查看java进程信息
jstack:jstack命令用于生成Java应用程序的线程转储快照,以便分析线程状态和死锁问题。它可以显示各个线程的堆栈跟踪信息,帮助定位和解决线程相关的问题。学习,学习2
jstat:jstat命令用于监控Java虚拟机的各种统计信息,例如垃圾回收情况、堆内存使用情况、类加载信息等。它可以提供实时的性能数据,用于分析和调整JVM的运行时行为。
jinfo:jinfo命令用于获取Java虚拟机的配置信息,例如系统属性、运行时参数等。它还可以动态修改虚拟机的某些参数,如堆内存大小、GC
jhat:jhat是Java堆分析工具,用于分析和浏览Java堆转储文件(heap dump)。它提供一个Web界面,用于可视化查看堆内存中的对象、引用关系和统计信息,帮助分析内存泄漏和性能问题。
jrunscript:jrunscript是一个命令行工具,用于执行JavaScript脚本。它可以与Java集成,访问Java类和方法,提供了一种在Java环境中运行和测试JavaScript的方式。
jvisualvm:jvisualvm是一个全功能的Java性能监控和分析工具,提供了各种监控和分析功能,包括内存使用情况、线程状态、垃圾回收、CPU使用等。它还支持插件扩展,可以集成其他工具和扩展功能。
jdeps:jdeps是一个依赖关系分析工具,用于分析Java类文件之间的依赖关系。它可以帮助开发人员检查和解决类之间的依赖关系问题,包括循环依赖、缺失依赖等。
jlink:jlink是一个Java模块化工具,用于创建自定义的JRE(Java Runtime Environment)镜像。它可以根据应用程序的需求,裁剪和优化JRE,只包含所需的模块和类库,减少运行时环境的大小。
jshell:jshell是一个交互式的Java编程工具,用于快速测试和尝试Java代码片段。它提供了一个命令行界面,可以即时执行Java代码,并提供实时反馈和结果展示。
jcmd:jcmd是一个通用的JDK命令工具,用于执行各种诊断和管理操作。它可以用于查看运行中的Java进程、生成线程转储、查看性能数据等。
jps -v查看进程启动时的JVM参数jstat -gc查看堆各分区大小、YGC、FGC次数和时长jinfo -flag查看和修改具体参数jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]vmid是进程id号,即jps查询到的java进程id
jmap -dump[:live], file=<file.hprof> <pid> 生成dump文件,:live只保存堆中存活的对象 jmap -heap <pid> 输出整个堆空间的详细信息,包括GC使用,堆配置信息,内存使用信息 jmap -histo[:live],file=<file.hprof> <pid> 输出堆空间中对象的统计信息,包括类,实例数量和合计容量,:live只统计堆中存活对象-XX:+HeapDumpOnOutOfMemoryError:开启自动生成
-XX:HeapDumpPath=/tmp/java_%p_%t.hprof:设置堆转储文件保存位置,以进程ID和事件戳命名
-XX:+HeapDumpBeforeFullGC:在进行FullGC前自动生成堆转储文件(HeapDumpAfterFullGC 实现在Full GC后dump)如果没有开启自动GC,则此参数无效。JDK9之后该参数已被删除
调优JVM参数主要关注停顿时间(STW)和吞吐量(运行时长/(运行时长+GC时长)),二者不可得兼,提高吞吐量会拉长停顿时间 如果应用程序跟用户基本不交互,就优先提高吞吐量。如果和用户交互频繁,就优先缩短停顿时间。
java -XX:+PrintFlagFinal -version:查看当前JVM参数设置
调整内存大小:
-XX:MetaspaceSize=128m:元空间默认大小
-XX:MaxMetaspaceSize=128m:元空间最大大小
-Xms1024m:堆初始大小,一般等于Xmx即可
-Xmx1024m:堆最大大小,设置为老年代存活对象大小的3-4倍
-Xmn256m:新生代大小,官方建议为Xmx的3/8左右
-Xss256k:栈最大深度大小
-XX:MaxDirectMemorySize=1024m:设置直接内存最大值,若不指定默认与堆最大值一致
调整内存比例:
-XX:SurvivorRatio=8:Eden:Survivor=8:2,默认E:S0:S1=8:1:1
-XX:NerRatio=4:新生代:老年代=1:4,默认值是2
YGC频繁时,可以提高新生代的比例、Eden在新生代的比例,让新生代不那么快被填满
修改垃圾回收器:
-XX:+UseSerialGC:设置Serial垃圾收集器(新生代)
-XX:+UseParallelOldGC:设置PS+PO,新生代使用功能Parallel Scavenge,老年代使用Parallel Old收集器
-XX:+UseConcMarkSweepGC:CMS垃圾收集器(老年代)
-XX:+UseG1GC:设置G1垃圾收集器
-XX:MaxGCPauseMillis:GC停顿时间,垃圾收集器会尝试各种手段达到这个时间(G1回收器默认200ms)
-XX:InitialTenuringThreshold=7:进入老年代最小的GC年龄,年轻代对象转换为老年代对象最小年龄值,JDK8默认15,JDK9默认7
-XX:PretenureSizeThreshold=1000000:新生代可容纳的最大对象数量,0代表没有限制
-XX:CMSInitiatingOccupancyFraction:使用多少比例的老年代后开始使用CMS收集,默认是68%,如果频繁发生SerialOld卡顿,应该调小
-XX:G1MixedGCLiveThresholdPercent=65:G1混合垃圾回收周期中要包括的旧区域设置占用率阈值,默认65%
GC日志:
-XX:+PrintGCDetails -Xloggc:/opt/tmp/myapp-gc.log:打印详细GC日志(JDK8)-Xlog:gc*:file=/opt/tmp/myapp-gc.log:打印GC日志(JDK9)-XX:+PrintGCTimeStamps:打印GC时间戳(以基准时间的形式)-XX:+PrintGCDateStamps:打印GC时间戳(以日期格式)-XX:GCTimeRatio=99:设置吞吐量99%,一般不低于95%-XX:+DisableExplicitGC:强制禁止显示调用System.gc()和Runtime.getRuntime().gc()。GC应由JVM自行控制,不建议显示进行GC。完整GC流程

Full GC触发机制
System.gc()时,系统建议执行Full GC,但不一定执行-XX:+UseSerialGC)-XX:+UseParallelOldGC)enhancer.setUseCache(false),即关闭用户缓存,那么每次创建代理对象都是一个新的实例,创建过多就会导致方法区溢出。JDK动态代理不会导致方法区溢出。内存泄漏9种情况