首页 文章 精选 留言 我的

精选列表

搜索[虚拟机隔离],共10004篇文章
优秀的个人博客,低调大师

Java 虚拟机诊断利器

作者 | 小白一只 【Arthas 官方社区正在举行征文活动,参加即有奖品拿~点击投稿】 背景 最近学习Java字节码过程中遇到了反射,有段代码是这样的: package com.example.classstudy; import java.lang.reflect.Method; /** * @author TY */ public class ReflectionTest { private static int count = 0; public static void foo() { new Exception("test#" + (count++)).printStackTrace(); } public static void main(String[] args) throws Exception { Class<?> clz = Class.forName("com.example.classstudy.ReflectionTest"); Method method = clz.getMethod("foo"); for (int i = 0; i < 20; i++) { method.invoke(null); } } } 就是一段简单的反射调用 foo 方法,执行 20 次,然后看执行结果: 可以看到在 15 次调用 foo 方法后,第 16 次调用 foo 方法是走的 GeneratedMethodAccessor1 来调用的。我嘞个擦,怎么回事,调着调着就不一样了,于是跟代码,跟到了下面这个类: 其中这句代码就是对反射调用的次数做了控制 if (++this.numInvocations > ReflectionFactory.inflationThreshold() && !ReflectUtil.isVMAnonymousClass( this.method.getDeclaringClass())) { MethodAccessorImpl var3 = (MethodAccessorImpl) (new MethodAccessorGenerator()) .generateMethod(this.method.getDeclaringClass(), this.method.getName(), this.method.getParameterTypes(), this.method.getReturnType(), this.method.getExceptionTypes(), this.method.getModifiers()); this.parent.setDelegate(var3); } this.numInvocations 的默认值是 0,而 ReflectionFactory.inflationThreshold() 默认是 15,当大于 15 的时候会通过 ASM 技术动态生成 GeneratedMethodAccessor1 类来调用 invoke 方法,但是,因为是动态生成的,我们怎么才能看到这个类实际长什么样子呢? Arthas 这个时候,就可以用上阿里的 arthas(阿尔萨斯)了。 首先下载 arthas: curl-Ohttps://alibaba.github.io/arthas/arthas-boot.jar 然后启动 arthas: java-jararthas-boot.jar 启动之后界面长这个样子: 其中什么 23012, 28436 等是当前环境中现有的 java 进程,然后需要连接到哪个进程就输前面的编号(1234 啥的),输了之后回车。那么我首先改写一下最开始的那个程序,让他不退出: package com.example.classstudy; import java.lang.reflect.Method; /** * @author TY */ public class ReflectionTest { private static int count = 0; public static void foo() { new Exception("test#" + (count++)).printStackTrace(); } public static void main(String[] args) throws Exception { Class<?> clz = Class.forName("com.example.classstudy.ReflectionTest"); Method method = clz.getMethod("foo"); for (int i = 0; i < 20; i++) { method.invoke(null); } System.in.read(); } } 重新启动程序之后,查看 arthas 界面: 可以看到 32480 正是我们运行的程序,输入编号 2 去连接到该进程: 然后就可以将动态生成的类 dump 下来: dumpsun.reflect.GeneratedMethodAccessor1 可以看到字节码被 dump 下来了,找到该文件用 javap 来查看: javap-c-v-p-lGeneratedMethodAccessor1.class 没有问题,可以查看到,然后剩下的就是人肉翻译字节码啦。。。 本篇关于Arthas的使用其实很少,我只是因为学到这个地方简单的用了下,但是已经感受到了 Arthas 的强大之处,它甚至还支持 web 界面。。。 相当厉害! Arthas 征文活动火热进行中 Arthas 官方正在举行征文活动,如果你有: 使用 Arthas 排查过的问题 对 Arthas 进行源码解读 对 Arthas 提出建议 不限,其它与 Arthas 有关的内容 欢迎参加征文活动,还有奖品拿哦~点击投稿 “阿里巴巴云原生关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的公众号。”

优秀的个人博客,低调大师

Java虚拟机运行流程

DOS:磁盘命令系统。 有空格的dos不管你是不是一体的默认为是一体 要说明他是一体的话要加双引号 dos中快速打开dos中的命令啊? dos:要想写入一个断命令就执行你的命令你就要告诉dos你要执行命令的夹子在那了。 告诉他了你就可以快速执行短命令 不管你要怎样在dos启动你的程序都要进入根目录下。 path:(又称环境变量)我们如果想在dos写一个快捷命令让他执行我们只能将他的路径告诉环境变量path, path:环境变量就是寄存了一些路径.地址数据,我们把路径告诉了path,path知道去哪里去找。 你配置好了path:我们把路径告诉了path,path就知道往这个路径下去搜索。 path是Java的吗,path是系统的,专为dos提供快捷命名配置你把路径告诉path今后你只要输入短的名称,他就会帮你在path搜索,搜索的到就运行搜索不到就报错。好处就是不用写那么长的路径名了。 配置完path要以封号结尾(;),path;可以帮你快速执行命令。 启动文件是exe文件启动的。java的环境变量中的启动和运行文件在bin目录。 Java运行时java.exe, 编译时javac。exe 多个路径使用分割符(;)隔开即可,配置完毕后要重启才可以读取新配置的数据。 写命令运行 和配置path(好处就是节省输入命令路径)方便。 path:就是在就是在dos写一个快捷命令如何写一个短命令让他快去执行,那就要把你的文件命令告诉path, path,不是Java的他是系统的命令。 运行的是class文件 java -version查询java版本 配置环境变量了计算机只会按照你配置的路径去寻找(计算机是死东西只会运算) classpath 是类文件的类需要在配置不需要要就不用配置,配置了他就会指定位置搜索。要想本地搜索 . ; JAVA_HOME; jdk总目录

优秀的个人博客,低调大师

Java虚拟机内存模型

章节 JVM结构 运行时数据区(Java run time data area) 方法区-线程共享 堆区 -线程共享 Java栈 -线程私有 native 本地方法栈-线程私有 PC寄存器 - 线程私有 类加载器子系统 ClassLoader 概述 类加载时机 ClassLoader 分类 ClassLoader 工作原理 装载 链接 初始化 执行引擎 1. JVM结构 1、JVM 主要由类加载器、Java运行时数据区、执行引擎以及本地方法接口组成。 2、Java 运行时数据区由 方法区、堆、Java栈、PC寄存器、本地方法栈组成。 3、本地方法栈、PC寄存器、Java栈是由每个线程私有的;方法区、堆是所有java线程共享的。 2.运行时数据区 2.1 Java 栈 1.Java栈与线程关联在一起,new Thread() 后会为当前线程创建对应的Java栈。 2.每个Java 栈中会包含多个栈帧,每个栈帧与每个运行中的方法对应起来。 3.运行一个方法创建一个栈帧,方法运行结束,栈帧弹出栈顶。 2.1.1 局部变量区 局部变量区 包含 方法参数、和局部变量、基本类型变量、对象引用。 2.1.2 操作数栈 进行入栈出栈基本操作。在计算时,操作数栈出栈,计算完毕后再入栈。 2.1.3 帧数据区 1.记录 存储类的相关信息的常量池的 指针 ,便于解析。 2.帮助方法正常返回:恢复调用该方法的栈帧、设置PC寄存器指向 调用方法对应的下一条指令、把返回值压入调用方法的栈帧中的操作 数栈中。 2.2 本地方法栈 本地方法栈类似于Java栈,主要存储本地方法调用状态。 本地方法栈为JVM调用native方法服务。 2.3 PC寄存器/程序计数器 记录当前线程即将执行的下一条指令的地址。 2.4 方法区 类型信息和类的静态变量都存储在方法区中 方法区中每个类存储了以下数据: 1.类及其父类的全限定名 2.类的类型 class or interface 3.访问的修饰符 (public abstract final) 4.实现的接口的全限定名的列表 5.字段信息 6.方法信息 7.静态变量 8.常量池 9.ClassLoader 引用 10.Class引用 注意:可见类的所有信息都存储在方法区中,由于方法区是线程共享的,所以必须保证线程安全。 举例:两个类要同时加载一个尚未被加载的类,那么一个类会请求它 的ClassLoader去加载需要的类,另一个类只能等待而不会重复加 载。 2.4.1 常量池 常量池本身是方法区中的一个数据结构: 1、常量池中存储了如字符串(有些地方称之为字符串池)、final 变量值,类名和方法名常量。 2.常量池中数据在编译器就被确定,保存在.class文件中。 分为两类: 字面量:final变量、字符串 引用量:类名、方法名、类和接口的全限定名 3.方法区对应持久代(Permanent Generation),默认大小16M,最大值 64M。大小通过参数来设置,-XX:permSize 指定初始值,-XX:MaxPermSize 指定最大值。 2.5 堆 1.堆是JVM管理的内存中最大的一块,是被所有Java线程共享的, 不是线程安全的,在JVM启动时创建。 2.堆用于存储对象实例以及数组值。 3.堆中有指向方法区中常量池中类信息的指针 4.堆中存放了指向方法表的指针 5.堆中实例数据包含了对象锁 monitor 对象, 2.5.1 分代管理模式-新生代、老年代 1.新生代(New Generation) 大多数情况下对象被分配在新生代,新生代由Eden Space 和两块相同大小的Survivor Space 组成。 后两者主要用于Minor GC 时的对象复制。 2.老年代 (Old Generation/Tenuring Generation) 在新生代存活时间较久的对象会被转入老年代,老年代进行垃圾回收的频率没有新生代高。 3.类加载器子系统(Class Loader) 3.1 类加载器概述 类加载器子系统负责加载编译好的.class 字节码文件,一般情况下类 在编译成.class 文件之后,立即被装入内存,使JVM可以实例化或以 其他方式使用加载后的类。JVM的类加载子系统支持在运行时的动态 加载(Java 反射),动态加载可以节省内存空间。 3.2 类加载的时机 类加载时机 含义 举例 静态加载 静态加载类,在编译时刻就需要加载所有可能使用到的类 如 new Word() 动态加载 属于延迟加载的模式,在java反射中会用到,首先节省内存,另外一个是动态加载类,这种方式在动态工厂方法中也会用到,这个生成类的util类只需要被加载一次就可以了 如 class.forName this.getClass() Class.class 三种方式实现运行时加载 3.3 ClassLoader 分类 1.启动类加载器 (Bootstrap ClassLoader),java rt.jar 负责加载java 核心类 2.扩展类加载器 (Extension ClassLoader),负责加载一些扩展功能的jar包 3.系统类加载器 (System ClassLoader ),负责加载启动参数中制定的ClassPath 中的jar 包及目录。我们自己写的Java类也是由该ClassLoader加载的。 4.用户自定义类加载器 (UserDefined Classloader):用户自定义类的加载规则,可以手动控制加载过程中的步骤。 3.4 ClassLoader的工作原理 类加载分为三个过程:装载、链接、初始化3.4.1 装载 1. 通过类的全限定名和Classloader 加载类,主要是将指定的.class 文件加载至jvm当中,类加载之后,jvm内部使用类的全限定名+ ClassLoader实例ID 标明类。 2.ClassLoader 实例 与 类实例位于堆中,他们的类信息位于方法区中 3.装载过程使用“ 双亲委派模型”,当一个ClassLoader要加载类时,他 会先请求他的双亲ClassLoader,即整个加载类的请求不断上抛,直 到启动类加载器。只有其双亲ClassLoader无法加载指定的类时,它 才会自己加载类。 4.不同类加载器之间是无法交互的,即使是同一个类,被不同的 ClassLoader加载,他们也无法感知彼此的存在。 3.4.2 链接 1.验证:校验.class文件的正确性,确保改文件是符合规范定义的 2.准备:为类分配内存,同时初始化类中的静态变量赋值为默认值。 3.解析:主要把类的常量池中的符号引用解析为直接引用。 3.4.3 初始化 定义:初始化类中的静态变量,并执行类中的static代码,构造函数。 初始化类的时机 1.通过new关键字、反射、clone、反序列化机制实例化对象 2.调用类的静态方法 3.使用类的静态变量或对其赋值 4.通过反射调用类的方法 5.初始化该类子类,其父类必须已经被初始化 6.具有main方法的类。

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册