当前位置: 首页 > news >正文

合肥霍山路网站建设提升学历教育

合肥霍山路网站建设,提升学历教育,桥头网站建设公司,有哪些企业网站做的不错1 内存结构 1.1 程序计数器 1.1.1 定义 Program Counter Register 程序计数器#xff08;寄存器#xff09; 作用#xff1a;是记住下一条 jvm 指令的执行地址 特点#xff1a; 是线程私有的#xff08;每个线程独有自己的一份#xff09;不会存在内存溢出 1.1.2 作…1 内存结构 1.1 程序计数器 1.1.1 定义 Program Counter Register 程序计数器寄存器 作用是记住下一条 jvm 指令的执行地址 特点 是线程私有的每个线程独有自己的一份不会存在内存溢出 1.1.2 作用 记住下一条 jvm 指令的执行地址 (0,3,4,5,...) 线程私有的 每个线程都有一个自己的程序计数器里面存储了自己线程运行到了哪条指令 1.2 虚拟机栈 1.2.1 定义 Java Virtual Machine Stacks (Java 虚拟机栈) 每个线程运行时所需要的内存称为虚拟机栈每个栈由多个栈帧(Frame)组成对应着每次方法调用所占用的内存每个线程只有一个活动栈帧对应当前正在执行的那个方法 栈线程运行需要的内存空间 栈中存储着多个栈帧每个栈帧对应着一个调用过的方法栈顶为活动栈帧是当前正在运行的函数当一个方法运行完成这个方法对应的栈帧就会出栈 问题辨析 垃圾回收是否涉及栈内存 不需要每次方法结束时栈内存就被回收掉了不需要等待垃圾回收垃圾回收是用来回收堆内存中的对象的 栈内存分配越大越好吗 可以用 -Xss size 指令设置栈内存的大小Linux macOS默认 1024 KBWindows 依赖虚拟内存的大小 方法内的局部变量是否线程安全 如果方法内局部变量没有逃离方法的作用访问是线程私有的它是线程安全的 如果是局部变量引用了对象对象是共有的并逃离方法的作用范围需要考虑线程安全 /*** 局部变量的线程安全问题*/public class d1_local_var_safe {// 多个线程执行这个方法public static void method1(String[] args) {int x 0;for (int i 0; i 5000; i) {x;}System.out.println(x);} }1.2.2 栈内存溢出 栈帧过多导致栈内存溢出。例如方法的递归调用 栈帧过大导致栈内存溢出 1.2.3 线程运行诊断 案例一CPU 占用过高 可以用 top 命令定位哪个进程对 CPU 的占用过高 找到进程后我们想进一步的定位到具体的线程可以用 ps 命令 ps H pid,tid,%cpu 可以把当前所有线程的 pid,tid,cpu的信息展示出来使用管道过滤出具体的进程号ps h -eo pid,tid,%cpu | grep 32655 jstack 进程id 命令可以列出Java虚拟机中的所有的 Java 线程 根据 ps 命令找到的线程号可以在 jstack 中找到对应的线程里面给出该线程的状态和问题代码行号 案例二程序运行很长时间没有结果 可能发生了死锁等等 使用 jstack 命令进行检查 1.3 本地方法栈 我们可以通过本地方法调用一些用C/CPP写的更底层的方法例如Object类中的clone , hashCode… 方法 1.4 堆 1.4.1 定义 Heap 堆 通过 new 关键词创建对象会使用堆内存 特点 他是线程共享的堆中对象需要考虑线程安全问题堆中有垃圾回收机制 1.4.2 堆内存溢出 不断的向堆中添加对象且这些对象无法回收一段时间后会导致堆内存溢出 1.4.3 堆内存诊断 package com.rainsun.d1_Java_memory_structure; /*** 堆内存演示*/ public class d2_heap_memory {public static void main(String[] args) throws InterruptedException {System.out.println(1.....);Thread.sleep(30000);byte[] array new byte[1024 * 1024 * 10]; // 10Mb 空间System.out.println(2.....);Thread.sleep(30000);array null;System.gc();System.out.println(3.....);Thread.sleep(100000L);} }查看堆内存信息 jps 找到当前运行的线程id jhsdb jmap --pid 线程id --heap 输出堆占用信息 1: 2: 3:没有G1 Heap了 jconsole 工具 图形界面的多功能的监测工具可以连续监测 1.5 方法区 方法区是线程共享的存储类相关的信息方法构造器特殊方法运行时常量池等等 Chapter 2. The Structure of the Java Virtual Machine (oracle.com) JDK1.6中的结构 使用 PermGen 永久代实现 JDK1.8中的结构 元空间实现使用操作系统中的本地内存实现 1.5.4 运行时常量池 常量池就是一张表虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等信息运行时常量池 常量池是 *.class 文件中的当程序运行的时候每个被加载的类它的.class文件中常量池信息就都会放入运行时常量池运行时常量池保存了所有被加载了的类中的常量池信息并把里面的符号地址变为真实地址 1.5.5 StringTable public static void main(String[] args) {String s1 a;String s2 b;String s3 a b;String s4 s1 s2; }反编译 常量池中的信息都会被加载到运行时常量池中这时 a , b 都是常量池中的符号还没有变成 Java 字符串对象ldc #2 会把 a 符号变为 “a” 字符串对象并把 “a” 放入 StringTable 中如果没有则加入新的有则不加入新的 s1s2s3 字符串对象的产生是发生在字符串常量池的 StringTable 中的 s4 字符串对象的产生是通过调用两次 makeConcatWithConstants 方法将常量池中的 “a” “b” 进行拼接在堆中创建了一个新的字符串变量最后存入临时变量 s4中的。 这是 JDK 21 反编译的结果JDK 8 不一样可能是 append.append.toString StringTable 特性 常量池中的字符串仅是符号第一次用到时才变为对象利用串池的机制来避免重复创建字符串对象字符串变量拼接的原理是 StringBuilder 1.8字符串常量拼接的原理是编译期优化可以使用 intern 方法主动将串池中还没有的字符串对象放入串池 public static main(String[] args){String s new String(a) new String(b); }StringTable 中创建了字符串对象 [“a”“b”] 在堆中产生了字符串对象因为使用了 new 来创建 “a”“b” “ab” intern: 将字符串对象放入 StringTable如果table中有则不会放入没有则放入并把 table 中的对象返回 String s2 s.intern(); // 堆中的 ab 被放入了 StringTable中了, 并将table中的ab返回public class d3_stringTable {// 常量池中的信息都会被加载到运行时常量池中这时 a , b 都是常量池中的符号还没有变成 Java 字符串对象// ldc #2 会把 a 符号变为 a 字符串对象并把 a 放入 StringTable 中如果没有则加入新的有则不加入新的public static void main(String[] args) {String s1 a;String s2 b;String s3 a b; //javac在编译期间的优化变成了 ab结果在编译期就已经确定了String s4 s1 s2; // 堆中的ab: new String(ab)String s5 ab; // s3 在table中的abString s6 s4.intern(); // table中ab已经有了返回table中的abSystem.out.println(s3 s4); //falseSystem.out.println(s3 s5); // trueSystem.out.println(s3 s6); // trueString x2 new String(c) new String(d);String x1 cd;x2.intern(); // table中 cd 已经存在了x2放不进去tablex2还是堆中的cdSystem.out.println(x1 x2); // false/** 最后两行代码的位置调换* String x2 new String(c) new String(d);* x2.intern(); // table 中 cd 不存在x2放入tablex2 变成了table中的cd* String x1 cd; // x1 用的是table中的cd* System.out.println(x1 x2); // true*/} }1.5.6 StringTable 位置 1.6 中的StringTable在PermGen永久代中实现它的回收时机比较晚容易造成永久代的内存空间不足 在1.8中就将StringTable放入堆Heap中实现它的垃圾回收时机触发比较早可以更快回收不用的字符串空间 1.5.7 StringTable 垃圾回收 那些没有用到的字符串常量会被垃圾回收 package com.rainsun.d1_Java_memory_structure;/*** 演示 StringTable垃圾回收* -Xmx10m* -XX:PrintStringTableStatistics : 打印 StringTable 信息* -XX:PrintGCDetails -verbose:gc 打印垃圾回收信息*/ public class d4_stringTable_GC {public static void main(String[] args) {int i 0;try {for (int j 0; j 100000; j) {String.valueOf(j).intern();i;}}catch (Throwable e){e.printStackTrace();}finally {System.out.println(i);}} }1.5.8 StringTable 调优 -XX:StringTableSize桶个数 可以设置String Table 中桶的个数类似于一个哈希表当表越大每个桶中链表的长度就越小查找的速度就越快考虑将字符串对象是否入池 如果字符串大量重复可以让字符串入池减少重复字符串存在在heap中 1.6 使用操作系统中的直接内存 1.6.1 Direct Memory 常见于 NIO 操作用于数据缓冲区分配回收成本较高但读写性能高不受 JVM 内存回收管理 传统的阻塞式 IO 读取数据的方式 CPU从Java的用户态转为系统的内核态这样可以读取磁盘中的文件到系统的缓冲区但是系统的缓冲区 Java 无法获取所以还需要将系统缓冲区中的数据传给Java缓冲区 使用直接内存进行文件读取 会产生一块 direct memory的区域操作系统和Java都可以读取 内存溢出问题 当direct memory占用太大会抛出内存溢出异常 1.6.2 分配和回收原理 使用了 Unsafe 对象完成直接内存的分配回收并且回收需要主动调用 freeMemory 方法 package com.rainsun.d1_Java_memory_structure;import sun.misc.Unsafe;import java.io.IOException; import java.lang.reflect.Field;public class d5_direct_memory {static int _1Gb 1024*1024*1024;public static void main(String[] args) throws IOException {Unsafe unsafe getUnsafe();// 分配内存long base unsafe.allocateMemory(_1Gb);unsafe.setMemory(base, _1Gb, (byte) 0);System.in.read();// 释放内存unsafe.freeMemory(base);System.in.read();}public static Unsafe getUnsafe() {try {Field f Unsafe.class.getDeclaredField(theUnsafe);f.setAccessible(true);Unsafe unsafe (Unsafe) f.get(null);return unsafe;} catch (NoSuchFieldException | IllegalAccessException e) {throw new RuntimeException(e);}} }ByteBuffer 的实现类内部使用了 Cleaner 虚引用来监测 ByteBuffer 对象一旦 ByteBuffer 对象被垃圾回收那么就会由 ReferenceHandler 线程通过 Cleaner 的 clean 方法调用 freeMemory 来释放直接内存 测试 public class d6_direct_byteBuffer {static int _1Gb 1024*1024*1024;public static void main(String[] args) throws IOException {ByteBuffer byteBuffer ByteBuffer.allocateDirect(_1Gb);System.out.println(分配完毕);System.in.read();System.out.println(开始释放);byteBuffer null;System.gc();System.in.read();} }原理 // 分配内存后 public static ByteBuffer allocateDirect(int capacity) {return new DirectByteBuffer(capacity); }DirectByteBuffer(int cap) { super(-1, 0, cap, cap, null);boolean pa VM.isDirectMemoryPageAligned();int ps Bits.pageSize();long size Math.max(1L, (long)cap (pa ? ps : 0));Bits.reserveMemory(size, cap);long base 0;try {base UNSAFE.allocateMemory(size);} catch (OutOfMemoryError x) {Bits.unreserveMemory(size, cap);throw x;}UNSAFE.setMemory(base, size, (byte) 0);if (pa (base % ps ! 0)) {// Round up to page boundaryaddress base ps - (base (ps - 1));} else {address base;}try { // Cleaner检测this对象(ByteBuffer)是否被垃圾回收如果被回收了就会调用clean方法调用 Deallocator 中的 run 方法 释放内存cleaner Cleaner.create(this, new Deallocator(base, size, cap));} catch (Throwable t) {// Prevent leak if the Deallocator or Cleaner fail for any reasonUNSAFE.freeMemory(base);Bits.unreserveMemory(size, cap);throw t;}att null; } // 实现 Runnable 接口 private static class Deallocator implements Runnable {private long address;private long size;private int capacity;private Deallocator(long address, long size, int capacity) {assert (address ! 0);this.address address;this.size size;this.capacity capacity;}// Deallocator 中的 run 释放了内存public void run() {if (address 0) {// Paranoiareturn;}UNSAFE.freeMemory(address); // 释放内存address 0;Bits.unreserveMemory(size, capacity);}}// clean 方法调用 run 方法 public void clean() {if (!remove(this))return;try {thunk.run(); // Deallocator 中的 run 被调用} catch (final Throwable x) {AccessController.doPrivileged(new PrivilegedAction() {public Void run() {if (System.err ! null)new Error(Cleaner terminated abnormally, x).printStackTrace();System.exit(1);return null;}});} }1.6.3 禁用显示垃圾回收 -XX:DisableExplicitGC 禁用显式的垃圾回收 显示垃圾回收写法 System.gc();这种垃圾回收都是 Full GC的回收比较满常用于性能调优 这可能会对Direct memory 的内存回收有影响因为这里的Direct memory的内存回收是需要Java中的对象被回收时才会被触发的 例如这里是ByteBuffer对象被回收触发了分配的直接内存的回收。 所以还是用Unsafe对象手动的调用 freeMemory 进行回收比较好
http://www.sadfv.cn/news/39015/

相关文章:

  • 网站备案归属地济宁定制网站建设推广
  • 建设自己的网站软文网站外包
  • 有网站专门做效果图网站推广产品
  • 个人网站 cdn企业在线设计网站
  • angularjs的网站模板移动互联网开发课程设计选题
  • 阜阳讯拓网站建设公司措美网站建设
  • 有没有做高仿的网站物联网解决方案
  • 网站建设使用的语言网站 要强化内容建设
  • 网站地图建设有什么用自助免费搭建网站
  • 设计素材网站上的素材可以商用吗织梦网站调用工具
  • 建论坛网站建设企业网站流程
  • 中天建设集团有限公司总网站帮人家做网站
  • 建专业外贸网站长沙市网站制作多少钱
  • 营销型网站的类型有哪些wordpress亲子模板
  • 培训医院网站建设江西建设职业技术学院招生信息网站
  • wordpress设置菜单导航西安seo技术培训班
  • 科技公司php网站模版郑州一凡网站建设
  • 网站页面优化签象客沧州网路运营中心
  • 怎么样创建做零食山楂的网站网页制作步骤图
  • 石家庄个人建站网站策划个人网页设计html代码免费
  • 网站建站哪个品牌好大型网站建设价格多少
  • 郑州网站建设的公司网站建设如何实现检索功能
  • 礼品网站如何做百度手机软件应用中心
  • 想做外贸做哪些网站好广告联盟平台怎么加入
  • 建立网站项目计划书模板网站面试通知表格怎么做
  • 黄石市下陆区建设管理局网站微网站建设报价表
  • 赣州网站建设 赣州网页设计塘厦镇网站仿做
  • 做淘宝网站怎么弄网页设计制作的软件有哪些
  • 网站平台建设项目书做ppt图片用的网站有哪些
  • 有实力的网站建设公司青岛网站开发公司