各种JAVA JDK的镜像分发:https://www.injdk.cn/

java是值传递还是引用传递

首先要明确知道什么是值传递,什么是引用传递;

1
2
3
4
5
6
void doSth(Object *obj) {
obj = new Object(); // 3
}

Object o = new Object(); // 1
doSth(o); // 2

我们根据上面这段代码来说一下两种传递时,1、2分别包含什么操作:

  • 值传递:doSth传递的是对象o的内存,在doSth函数内部生成了obj的栈内存指向了o的内存地址,
    所以改变了obj的值,不会影响外面o的指向,用图表示:

  • 引用传递:传递的是别名,参数表示的地址和内存都一样,用图表示:

如何判断是值传递还是引用传递,只需要看在函数中,传进来的参数在重新赋值的情况下,是否会改变原参数,比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void doSth(Object *obj) {
obj = new Object();
// 而不是 obj.doXXX(xx);
}

Object o = new Object();
Object o2 = o;
#Object o2 = &o; // 取地址符
doSth(o);

if(o == o2) {
print("值传递");
}
if(o == o2) {
// 原参数变了
print("引用传递");
}

参考:https://blog.fearcat.in/a?ID=00650-2bba8274-4da2-415e-ab26-5713820b1d25

最后,我们思考另外一个问题,为什么java 里没有指针?

java里为什么没有指针?

java认为:

  • 开发人员应该更多的关注业务代码,尽量帮你完成不需要关注的操作:指针管理、内存管理;
  • 稳定问题,容易出现指针越界(指针指向的是地址,可以前后移动)
  • 安全问题(可能是因为指针可以指向任意内存地址?)

<Exception encountered during context initialization – cancelling refresh attempt: org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name ‘xxx’ defined in class path resource [xxx]

  • 问题

<Exception encountered during context initialization – cancelling refresh attempt: org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name ‘xxx’ defined in class path resource [xxx]: Cannot register bean definition [Root bean: class [null]; scope=refresh; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=false; primary=false; factoryBeanName=redisTicketRegistryConfiguration; factoryMethodName=ticketRegistry; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/apereo/cas/config/RedisTicketRegistryConfiguration.class]] for bean ‘scopedTarget.ticketRegistry’: There is already [Root bean: class [null]; scope=refresh; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=false; primary=false; factoryBeanName=casCoreTicketsConfiguration; factoryMethodName=ticketRegistry; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/apereo/cas/config/CasCoreTicketsConfiguration.class]] bound.>

  • 问题溯源

org/springframework/spring-beans/5.2.12.RELEASE/spring-beans-5.2.12.RELEASE-sources.jar!/org/springframework/beans/factory/support/DefaultListableBeanFactory.java:944

  • 解决

spring.main.allow-bean-definition-overriding: true

[org.springframework.boot.context.logging.ClasspathLoggingApplicationListener] –

  • 问题

spring-boot 项目无法启动,无错误提示

  • 解决思路

我们找到 Application failed to start with classpath: unknown 这句话提示的位置,

/Users/sucre/.m2/repository/org/springframework/boot/spring-boot/2.3.7.RELEASE/spring-boot-2.3.7.RELEASE-sources.jar!/org/springframework/boot/context/logging/ClasspathLoggingApplicationListener.java:54

打个断点,发现 event 有个 Exception 变量,可以查到具体的原因,手动执行 e.printStackTrace(); 就能找出原因所在了

  • 解决

至于我的问题是,yaml 配置有问题,而且找了很多遇见这种问题的同学,基本都是 yaml 配置错误

VisualVM 如何连接远程 K8S 中的服务

jVisualVM = VisualVM

  1. 首先修改服务启动参数:

    ““
    -Dcom.sun.management.jmxremote
    -Dcom.sun.management.jmxremote.ssl=false
    -Dcom.sun.management.jmxremote.authenticate=false
    -Dcom.sun.management.jmxremote.port=[port]
    -Dcom.sun.management.jmxremote.rmi.port=[port]
    -Djava.rmi.server.hostname=localhost

    1
    2
    3
    4
    5
    6
    7
        
    > `-Djava.rmi.server.hostname` 是否一定要 `localhost` ?

    2. 如果无法直连 K8S,则开启端口转发

    ```shell script
    kubectl --kubeconfig [config-file] port-forward svc/[service] [port:port] -n [namespace]
  2. 配置 visualvm

文件(F) -> 添加JMX连接… -> 输入 127.0.0.1:[port]

see: JMX – 远程监控JVM

DDD开源项目

内联

inlining: 内联,比如user.getName() 会被优化为 user.name
java中针对内联的优化:https://blog.csdn.net/yunxizixuan/article/details/80905086
优缺点:https://xduwq.blog.csdn.net/article/details/106652218(不知道不同语言是否想通)

JVM优化(20210816)

java -Xms2048m -Xmx2048m -Xmn1228m -XX:SurvivorRatio=5 -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m -Xss512K -XX:+DisableExplicitGC -XX:+UseParallelGC -XX:ParallelGCThreads=2 -XX:+UseParallelOldGC -XX:MaxGCPauseMillis=200 -XX:+UseAdaptiveSizePolicy -XX:+PrintClassHistogram -XX:+PrintGCDetails -Xloggc:/data/tgbc/gclogs/${jar_service}/gc.$$.log -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC -jar admin-1.0-SNAPSHOT.jar –spring.profiles.active=pro

tcpdump使用
GET : tcpdump -A -s 0 ‘tcp port 80 and (((ip[2:2] – ((ip[0]&0xf)<<2)) – ((tcp[12]&0xf0)>>2)) != 0)’
POST: tcpdump -X -s 0 ‘tcp port 80 and (((ip[2:2] – ((ip[0]&0xf)<<2)) – ((tcp[12]&0xf0)>>2)) != 0)’

task执行一段时间停掉了

1. spring schedule线程池默认大小为1;

2. RestTemplate默认使用HttpClient,他的默认连接超时时间:-1,默认读取超时时间:-1; 调用接口时,读取阻塞,从而导致task不可用;

前后端分离,无法登陆获取jsessionid

前后端分离调登录接口的一个问题,调用(POST)登录接口不会创建jsessionid,导致后面的接口拿不到用户信息,只有先调用任何一个GET请求,先生成jsessionid,再去掉登录接口,才能保证后续接口正常调用

解决:设置server.session.cookie 的 httpOnly=false, secure=false,这样post请求就能生成 JSessionid

lombok 生成构造函数时,加上变量的注解

场景:比如我想把 @Qualifier 加到 lombok @RequiredArgsConstructor 注解自动生成的构造函数的参数上,怎么破?

# Copy the Qualifier annotation from the instance variables to the constructor
# see https://github.com/rzwitserloot/lombok/issues/745
lombok.copyableAnnotations += org.springframework.beans.factory.annotation.Qualifier
这是最近在lombok 1.18.4中引入的;

不这样做的话,可能会遇到:Parameter 1 of constructor in xxx.WeWorkController required a single bean, but 2 were found;

效果:

/////////////////////////////////////////////////////////////////////////////////////////////////
////// WeWorkController.java
/////////////////////////////////////////////////////////////////////////////////////////////////
@RequiredArgsConstructor
public class WeWorkController {
 
    @Qualifier("wxCpZService")
    final WxCpService zService;
 
    @Resource(name = "wxCpOAService")
    final WxCpOAService wxCpOAService;
}
 
/////////////////////////////////////////////////////////////////////////////////////////////////
////// WeWorkController.class
/////////////////////////////////////////////////////////////////////////////////////////////////
public WeWorkController(@Qualifier("wxCpZService") final WxCpService zService, final WxCpOAService wxCpOAService) {
    this.zService = zService;
    this.wxCpOAService = wxCpOAService;
}

@MockBean 引发的 NoUniqueBeanDefinitionException

org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type ‘com.xxx.goods.infrastructure.dao.mapper.PrdGoodsMapper’ available: expected single matching bean but found 2: prdGoodsMapper,com.digibms.goods.infrastructure.dao.mapper.PrdGoodsMapper#0

问题描述:@MockBean 导致出现重复的bean:com.digibms.goods.infrastructure.dao.mapper.PrdGoodsMapper#0,实际的bean:prdGoodsMapper

解决方法:

@MockBean(name = "prdGoodsMapper") // name 和 实际的bean的name一致即可

see:https://github.com/spring-projects/spring-boot/issues/6541#issuecomment-238524659

WebMvcConfigurationSupport 导致 json 转换失效

问题:项目中自定义了 WebMvcConfigurationSupport,用来添加自己的拦截器,但 WebMvcConfigurationSupport 这个类里面实现了默认的 HttpMessageConverter,
导致我在其他地方配置的 ObjectMapper、application.yml(spring.jackson.date-format: yyyy-MM-dd HH:mm:ss) 均没有生效)

思路:我们去看 org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#messageConverters 中的 MappingJackson2HttpMessageConverter 是从哪里生成的,
它的 org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter#objectMapper 是从哪里注入的

解决:

  1. 依靠 spring 进行解决
  2. 使用 WebMvcConfigurer 代替 WebMvcConfigurationSupport,同时使用下面的代码注册 ObjectMapper
ObjectMapper objectMapper = new ObjectMapper();
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
objectMapper.registerModule(javaTimeModule);

springboot不允许请求参数带特殊字符,如:{},会报400错误

其实是服务器(tomcat、undertow)不支持,需要单独配置

tomcat

TODO

undertow

@Component
public class MyWebServerCustomizer implements WebServerFactoryCustomizer<UndertowServletWebServerFactory> {
 
    @Override
    public void customize(UndertowServletWebServerFactory factory) {
        factory.addBuilderCustomizers(builder -> builder.setServerOption(UndertowOptions.ALLOW_UNESCAPED_CHARACTERS_IN_URL, Boolean.TRUE));
    }
}

参考:https://juejin.cn/post/6844903913142009863

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注