震惊-spring单例不单例了
为什么我的单例bean会多次初始化?
背景代码如下,两个aop切入的类,都各自依赖的第三方提供的bean(必须是未初始化的,如果你没有redisson,你可以任意依赖其他的未初始化的bean)
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576@Slf4j@Componentpublic class RecordException extends AbstractPointcutAdvisor { @Resource Redisson redisson; @Override public Pointcut getPointcut() { return new Pointcut() { @Override public ClassFilter g ...
spring的@lazy注解
问题@Lazy能干什么?
123456789@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.FIELD})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Lazy { /** * Whether lazy initialization should occur. */ boolean value() default true;}
如何使用可用在类上、方法返回值上、方法上、构造方法上、参数上、以及字段上
类上、方法上、方法返回值上生成的bean懒加载,只有用到他的时候才会加载
12// 生成beanDefinition的时候会扫描注解,调用此方法,判断是否有Lazy注解,把beanDefinition的lazy属性变为true。AnnotationConfigUtils.processCommonD ...
远程执行java和shell(backDoor)
远程实时执行java代码和shell脚本。可通过http请求直接在服务器运行
代码
需要部署到服务端,在springMVC框架内,依赖groovy脚本解析器
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687public interface Debug { @Component class Java extends GenericServlet { @Autowired AutowireCapableBeanFactory beanFactory; private final GroovyClassLoader groovyClassLoader = new GroovyClassLoader(); public Stri ...
记录发现redissonBug并提交修复的历程
背景redis cluster集群模式下3主3从,用redisson,scan命令会漏扫非cluster集群下没有问题,lettuce也没有问题,只有redisson+cluster+scan才有会有问题
发现的历程搞库存重构,存放在redis的库存数据要更改名称,肯定不能用keys命令,keys会阻塞,时间复杂度是O(n)所以用scan,但发现scan总是漏扫数据,用Lettuce就没有问题,所以断定是redisson源码出现问题
找问题的历程分析源码,从scan开始,源码如下
建议debug阅读源码,不然容易混乱本地没有环境建议远程debug,在jvm启动脚本加上-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=16770 用idea连接即可远程debug
分析源码scan原理调用scan会返回一个迭代器,通过迭代器scan会从头扫到尾,直至cursorId=0源码如下
12345678910111213141516171819202122232425262728293031323334353 ...
java安全点safePoint以及JIT
什么是JITJust In Time(即时编译)一般程序遵循90-10原则,即运行时的90%时间里计算机是在处理其中10%的代码,java也是,jvm频繁的解释字节码也挺累的,因为还要翻译成机器码
,所以JIT的宗旨就是在运行过程当中找出热点代码并编译成二进制的机器语言(深度优化),这样就能很好的提高java的执行效率
假如Java的某个方法有1M次调用,通过jit优化此方法之后前后差100个指令,那么1M次调用,你就节省了0.1G个指令(1GHZ=10^3MHZ=10^6KHZ=10^9HZ)假设cpu处理频率为2.5GHz,优化后变为2.6GHz,相当于提升了4%的性能。如果优化的更多或者调用次数更多则性能提升的空间越大
一般都会优化哪些内容?
死代码删除如下代码,变量i是无任何意义的
1234public static void main(String[] args) { int i = 1; System.out.println("hello world");}
方法内联jit中非常重要的一环
将目标方法的方法体纳入编 ...
java内存模型和GC以及锁
让我们带着问题一探究竟一个Object对象占用几个字节,里面内容都是什么(对象占用大小)?在哪里分布呢(内存模型)?什么时候会销毁(GC)?
klass是java中,类的元信息在jvm中的表现形式,就是在c++中,类的元信息是通过klass来表示的
对象占用大小new Object();会占用多少内存呢?答案是16字节=128比特位=128bits
为什么是16字节呢?而不是17或者15? 这是因为8个字节=1byte,所以只能是8的倍数,那么是8,要么是16、24、32 那为什么是16,而不是24、32?因为这得取决于里面的内容是什么
里面内容是什么呢?对象头和数据体两大部分
1. 对象头
前面8个字节为markword,记录对象被上锁的各种状态或者垃圾回收和hashcode相关的信息默认无锁的情况如下,有锁的情况参考java锁
64位系统中(64bit)未使用:25位hashcode: 31位存储对象的System.identityHashCode(),采用延迟加载技术未使用:1位gc分带年龄: 4位偏向锁的标记:1位当前对象的锁的状态:2位25+ ...
jvmClassLoader过程及原理
classLoader加载class过程都是通过classLoader加载的class,如果已经加载过则不可以再次加载,但是可以通过不同的classLoader加载同一个class
都有哪些类加载器呢
引导类加载器=BootstrapClassloader是使用C++语言实现的,负责加载JVM虚拟机运行时所需的基本系统级别的类,如java.lang.String, java.lang.Object等等由于是C++实现的所以通过Object.class.getClassLoader() == null,无法访问
扩展类加载器=ExtClassLoader是由Bootstrap加载的此类此类加载器默认加载JAVA_HOME/jre/lib/ext/目录下的所有jar包,当然也可以加载由java.ext.dirs系统属性指定的jar包,用来加载java的扩展库,用户也可以直接使用此类加载器
应用类加载器=AppClassLoader是由AppClassLoader加载的此类此类加载器默认加载用户编写的class
双亲委派意思是多个亲戚,将加载class的任务委任给多个亲戚。以上三个类加载是 ...
定义swagger通用接口文档
我们用的swagger版本为
12345678910111213141516171819202122232425262728<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version></dependency><dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>swagger-bootstrap-ui</artifactId> <version>1.9.6</version></dependency><dependency> <groupId>com.spring4all</groupId ...
java-agent
简介
什么是java-agent、作用是什么、怎么用、原理是什么?java-agent可以理解为是一个代理程序,非主程序,代理程序可以做的事情就很多了,取决于你想写什么逻辑比如说Alibaba开源的Java诊断工具也可以动态的替换字节码,实现代码热更新的效果
原理通过java-agent程序我们可以获取到Instrumentation实例,得到此实例之后可以干的事情就很多了,比如说aop字节码增强,或者重新定义class等
具体原理可参考1:美团的技术分享-agent原理2:美团的技术分享-字节码增强原理
agent程序可以在主程序启动之前启动,做你想做的操作,需要编写逻辑代码并封装成Jar包,并在jvm 启动命令添加 -[javaagent|agentlib]:agentJar包的路径,jdk1.5之后才可以jar包中的class方法signature必须为 public static void premain(String agentArgs, Instrumentation inst)
也可以在主程序运行过程中启动,通过jdk自带的方法VirtualMachi ...
踩坑发现bug之解决springRemoteRestart不起作用
springDevTools提供了热部署的工具,按照网上的教程本地可以完美的支持热部署,但是一用到远程热部署(remoteRestart)就失效,热部署失败,抛ClassCastException异常为了解决这个问题,咱们今天分析一下他的原理,为什么本地可以热部署,远程热部署就会抛异常
技术栈:springBoot + MVC + DUBBO + NACOS + maven打包插件spring-boot-maven-plugin
热部署原理分析当我们修改class时,springDevTools利用了不同的classLoader重新加载class,并重新启动spring,使其生效优点就是已经加载过的class并不会重新加载以便节省性能,只针对动态修改的class重新加载即可
已加载的class无法在线卸载,只能用新的classLoader去加载,这样就起到了热部署的效果旧的classLoader以及对应加载过的class会被GC回收
在springBoot启动的时候,监听启动时的事件,然后用自己的热部署classLoader去重新启动spring(通过反射再次 ...