如何替换 JDK 的类

如何替换 JDK 的类

如何替换jdk中的类呢?Java提供了endorsed技术。

关于 endorsed :可以的简单理解为 -Djava.endorsed.dirs 指定的目录面放置的jar文件,将有覆盖系统API的功能。但是能够覆盖的类是有限制的,其中不包括java.lang包中的类(出于安全的考虑)。

为什么必须使用 endorsed 进行替换 jdk 中的类呢?

因为java是采用双亲委派机制进行加载class类的。而jdk提供的类只能由类加载器Bootstrap进行加载。如果你想要在应用程序中替换掉jdk中的某个类是无法做到的,所以java提供了endorsed来达到你想要替换到系统中的类。

使用endorsed的两种方式:

  • 运行的时候加上 -Djava.endorsed.dirs=D:\endorsed(jar包存放目录) 参数
  • 将修改后的jar包放在:$JAVA_HOME/jre/lib/endorsed 、$JAVA_HOME/lib/endorsed 下面

实例

本实例通过修改ArrayList来试验:

  1. 新建maven工程,在工程中新建java.util.ArrayList

  2. 复制jdk中ArrayList源码到自己创建的ArrayList,并修改构造方法如下:

image-20200911114253815

  1. 将工程打包成jar,复制到endorsed文件夹中
  2. 新建测试类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.idea4j.endorsed.test;
import java.util.ArrayList;
import java.util.List;
/**
* -Djava.endorsed.dirs=D:\idea4j-endorsed\endorsed
* -XX:+TraceClassLoading
*/
public class Test {
public static void main(String[] args) {
List list = new ArrayList();
System.out.println(1);
}
}
  1. 修改运行参数,如图

image-20200911114058420

  1. 运行Test,结果如下:

image-20200911114454953

看到Test类调用了我们修改的ArrayList,说明我们成功覆盖了jdk的类

但我们只调用一次new ArrayList(),为什么日志输出了这么多次呢?

我们在运行参数中在加入-XX:+TraceClassLoading看类加载过程可知,虚拟机启动时,有一些类调用了ArrayList默认构造器

image-20200911123505455

上面我们使用了修改运行参数的方法,下面我们再试验第二种方法,把jar包copy到$JAVA_HOME/jre/lib/endorsed下,结果和上面一样。

但是copy到$JAVA_HOME/lib/endorsed下,结果是没有覆盖成功。这是为什么呢?如图,java-home应该为实际运行环境的目录。

image-20200911130242199

经查看项目jdk配置

image-20200911125011220

classpath指定的是jre,所以,把jar包copy到$JAVA_HOME/jre/lib/endorsed下才能成功也就说的通了。

####

小程序

小程序

项目里边生成了不同类型的文件:

  1. .json 后缀的 JSON 配置文件
  2. .wxml 后缀的 WXML 模板文件
  3. .wxss 后缀的 WXSS 样式文件
  4. .js 后缀的 JS 脚本逻辑文件

小程序目录结构

image-20200927130658471

JSON配置

小程序中各个json文件的用途:

小程序配置app.json

image-20200927130854683

当前小程序的全局配置,包括了小程序的所有页面路径、界面表现、网络超时时间、底部 tab 等。

我们简单说一下这个配置各个项的含义:

  1. pages字段 —— 用于描述当前小程序所有页面路径,这是为了让微信客户端知道当前你的小程序页面定义在哪个目录。
  2. window字段 —— 定义小程序所有页面的顶部背景颜色,文字颜色定义等。

工具配置 project.config.json

页面配置 page.json

WXML 模板

从事过网页编程的人知道,网页编程采用的是 HTML + CSS + JS 这样的组合,其中 HTML 是用来描述当前这个页面的结构,CSS 用来描述页面的样子,JS 通常是用来处理这个页面和用户的交互。

WXSS 样式

WXSS 具有 CSS 大部分的特性,小程序在 WXSS 也做了一些扩充和修改。

  1. 新增了尺寸单位。在写 CSS 样式时,开发者需要考虑到手机设备的屏幕会有不同的宽度和设备像素比,采用一些技巧来换算一些像素单位。WXSS 在底层支持新的尺寸单位 rpx ,开发者可以免去换算的烦恼,只要交给小程序底层来换算即可,由于换算采用的浮点数运算,所以运算结果会和预期结果有一点点偏差。
  2. 提供了全局的样式和局部样式。和前边 app.json, page.json 的概念相同,你可以写一个 app.wxss 作为全局样式,会作用于当前小程序的所有页面,局部页面样式 page.wxss 仅对当前页面生效。
  3. 此外 WXSS 仅支持部分 CSS 选择器

更详细的文档可以参考 WXSS

JS 逻辑交互

目录结构

小程序包含一个描述整体程序的 app 和多个描述各自页面的 page

一个小程序主体部分由三个文件组成,必须放在项目的根目录:app.js,app.json,app.wxss。

一个小程序页面由四个文件组成,分别是js,wxml,json,wxss。

注意:为了方便开发者减少配置项,描述页面的四个文件必须具有相同的路径与文件名。

zookeeper选举规则

zookeeper选举规则

角色:

1.LOOKING:竞选

​ 2.OBSERVING:观察

​ 3.FOLLOWING:跟随者

​ 4.LEADER:领导者

投票信息:

​ 1.logicalclock(electionEpoch):本地选举周期,每次投票都会自增

​ 2.epoch(peerEpoch):选举周期,每次选举最终确定完leader结束选举流程时会自增(真正zxid的前32位)

​ 3.zxid:数据ID,每次数据变动都会自增(真正zxid的后32位,zxid一共64位)

​ 4.sid:该投票信息所属的serverId

​ 5.leader:提议的leader(被提议的server的serverId,即sid)

没有leader时

投票比较规则:

​ 1.epoch大的胜出,否则进行步骤2

​ 2.zxid大的胜出,否则进行步骤3

​ 3.sid大的胜出

消息队列

消息队列

graph LR
消息队列 –> B[队列] –> B1(使用场景)
B1 –> 应用解耦
B1 –> 服务通信
B1 –> 削峰填谷
B1 –> 消息广播
B –> B2(消息协议)
B2 –> JMS
B2 –> AMQP
B –> B3(常用队列)
B3 –> RabbitMQ
B3 –> ActiveMQ
B3 –> RocketMQ
B3 –> Kafka

springboot启动器

编写springboot启动器(starter)

命名规则

  • 官方 spring-boot-starter-模块名
  • 非官方(如我们自己编写的) 模块名-spring-boot-starter

模块结构

  • Xxx-spring-boot-starter

    引如自动装配模块,一般是个空工程

  • Xxx-spring-boot-autoconfigure

    核心代码中的类文件:
    1、XxxAutoConfiguration 自动配置类
    2、XxxProperties 属性文件加载类,通过@EnableConfigurationProperties({XxxProperties.class})注入到spring容器中,使得在XxxAutoConfiguration中可以直接注入使用配置属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@Configuration:定义配置类
@EnableConfigurationProperties:属性类
@AutoConfigureAfter: 自动配置应在XXX的自动配置类之后应用。
@AutoConfigureBefore: 自动配置应在XXX的自动配置类之前应用
@AutoConfigureOrder:定义配置类执行的顺序
@ConditionalOnBean:当容器里有指定的Bean 时才生成
@ConditionalOnMissingBean:当容器里没有指定Bean 时才生成
@ConditionalOnClass:当类路径下有指定的类时才生成
@ConditionalOnMissingClass:当类路径下没有指定的类时才生成
@ConditionalOnExpression:基于SpEL 表达式作为判断条件。
@ConditionalOnJava:基于JVM 版本作为判断条件。
@ConditionalOnJndi:在JNDI存在的条件下查找指定的位置。
@ConditionalOnProperty:指定的属性是否有指定的值。
@ConditionalOnResource:类路径是否有指定的值。
@ConditionalOnSingleCandidate:当指定Bean 在容器中只有一个,或者虽然有多个但是指定首选的Bean。
@ConditionalOnWebApplication:当前项目是Web 项目的条件下。
@ConditionalOnNotWebApplication:当前项目不是Web 项目的条件下。

spring.factories配置

在Xxx-spring-boot-autoconfigure模块下src/main/resources新建文件夹META-INF,然后新建一个spring.factories文件

1
2
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.xxx.xxx.XxxAutoConfiguration

为ConfigurationProperties类生成元信息.

在我们的autoconfiguration的模块中添加如下jar包依赖

1
2
3
4
5
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>

问题大全

Mycat,看过源码吗?聚合这块儿它怎么处理的

限流怎么搞

知道大概怎么个流程么,写个rpc框架

jvm内存了解么,新生代出问题了的话,你知道是为什么吗?怎么判断

生产jvm调优有过经验么

分布式事务怎么处理

Pinpoint安装使用

Pinpoint安装使用

Pinpoint是用于用Java / PHP编写的大规模分布式系统的APM(应用程序性能管理)工具。受Dapper的启发,Pinpoint提供了一种解决方案,可通过跟踪跨分布式应用程序的事务来帮助分析系统的整体结构以及其中的组件如何互连。

你一定要检查精确定位,如果你想

  • 一目了然地了解您的应用程序拓扑
  • 监控应用程序的实时
  • 获得每笔交易的代码级可见性
  • 安装APM代理而无需更改任何代码
  • 对性能的影响最小(资源使用量增加约3%)

一、下载pinpoint包

https://github.com/naver/pinpoint/releases 下载

  1. pinpoint-agent.tar.gz
  2. pinpoint-collector.war
  3. pinpoint-web.war

二、安装 HBase

修改 hbase-site.xml 为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<configuration>
<property>
<name>hbase.rootdir</name>
<value>file:///home/testuser/hbase</value>
</property>
<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/home/testuser/zookeeper</value>
</property>
<property>
<name>hbase.unsafe.stream.capability.enforce</name>
<value>false</value>
</property>
</configuration>

执行 bin/start-hbase.sh启动 hbase

执行 ./hbase shell hbase-create.hbase 文件创建表等

三、启动 pinpoint-web

修改 pinpoint-web.war 包配置文件(默认)

1
2
3
4
5
修改 WEB-INF\classes\hbase.properties 文件
hbase.client.host 设置为 hbase 所用的 zk 地址
修改 WEB-INF\classes\pinpoint-web.properties 文件
cluster.zookeeper.address 修改为给 Pinpoint 准备的 zk 地址

将 war 包放到 tomcat 中启动

四、启动 pinpoint-collector

修改 pinpoint-collector.war 包配置文件(默认)

1
2
3
4
5
修改 WEB-INF\classes\hbase.properties 文件
hbase.client.host 设置为 hbase 所用的 zk 地址
修改 WEB-INF\classes\pinpoint-collector.properties 文件
cluster.zookeeper.address 修改为给 Pinpoint 准备的 zk 地址

可以将 pinpoint-web 和 pinpoint-collector 放到一个 tomcat 中启动

五、配置 Agent

解压 pinpoint-agent.tar.gz,修改 pinpoint.config 中的 profiler.collector.ip 改为部署 collector 的机器ip

六、启动应用服务

1
2
3
java -javaagent:/opt/agent/pinpoint-bootstrap-1.8.0-SNAPSHOT.jar -Dpinpoint.agentId=dubbo-provider-id -Dpinpoint.applicationName=dubbo-provider -jar dubbo-provider-0.0.1-SNAPSHOT.jar
java -javaagent:/opt/agent/pinpoint-bootstrap-1.8.0-SNAPSHOT.jar -Dpinpoint.agentId=dubbo-consumer-id -Dpinpoint.applicationName=dubbo-consumer -jar dubbo-consumer-0.0.1-SNAPSHOT.jar

如果是通过 tomcat 启动,则需要修改 bin/catalina.sh 文件

1
2
3
CATALINA_OPTS="$CATALINA_OPTS -javaagent:/opt/agent/pinpoint-bootstrap-1.8.0-SNAPSHOT.jar"
CATALINA_OPTS="$CATALINA_OPTS -Dpinpoint.agentId=AGENT_ID"
CATALINA_OPTS="$CATALINA_OPTS -Dpinpoint.applicationName=APPLICATION_TEST"