Skip to main content

java redis client

· One min read

背景

背景是需要了解java的redis是怎么使用的

redission

redisson 是java的一个redis客户端

接入spring boot 遇到的问题

spring boot 启动遇到了问题redirection loop detected , 是因为测试环境redis是cluster 模式 , 但是本地配置是单个节点,所以会有问题

org.springframework.dao.InvalidDataAccessApiUsageException: MOVED redirection loop detected. Node redis://10.2.26.106:6379 has further redirect to redis://xxx:6379; nested exception is org.redisson.client.RedisException: MOVED redirection loop detected. Node redis://10.2.26.106:6379 has further redirect to redis://xxx:6379

解决方案 : 在配置文件改成cluster 就可以正常get 和set 了

相关阅读

java volatile

· 5 min read

背景

了解java的volaite 内容

volatile

volatile 在jls有几个描述:

  • keyword
  • filed modified

volatile目的

volatile详细描述在: 8.3.1.4 volatile Fields

The Java programming language allows threads to access shared variables (§17.1).
As a rule, to ensure that shared variables are consistently and reliably updated, a
thread should ensure that it has exclusive use of such variables by obtaining a lock
that, conventionally, enforces mutual exclusion for those shared variables.
The Java programming language provides a second mechanism, volatile fields,
that is more convenient than locking for some purposes

翻译:

在java中,可以由不同的线程共享一个变量.
线程必须通过获得锁来保证共享的变量可以被可靠和一致的更新.
简单来说,就是使用mutual的排他性来获取这个特性
java除了通过锁,还有另外一个机制来访问和更新共享变量,这就是volatile fields.
在某些情况下volatile field会比锁更加方便

visibility, ordering and atomicity

同步有三个问题:

  • 可见性
  • 排序
  • 原子性

jsr-133 里面有三个不正常同步会出现的问题 ,原文如下:

If a program is not correctly synchronized, then three types of problems can appear:
visibility, ordering and atomicity.

orderging

下面是jsr133 里面给的例子:

分别有两个线程: threadOne 和线程threadTwo

class BadlyOrdered {
boolean a = false;
boolean b = false;

void threadOne() {
a = true;
b = true;
}

boolean threadTwo() {
boolean r1 = b; // sees true
boolean r2 = a; // sees false
return r1 && !r2; // returns true
}
}

在网上找了个c++ 版本的cpu指令重排的例子来源

命名为 reorder.cpp

#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>

// Set either of these to 1 to prevent CPU reordering
#define USE_CPU_FENCE 0
#define USE_SINGLE_HW_THREAD 0 // Supported on Linux, but not Cygwin or PS3

#if USE_SINGLE_HW_THREAD
#include <sched.h>
#endif


//-------------------------------------
// MersenneTwister
// A thread-safe random number generator with good randomness
// in a small number of instructions. We'll use it to introduce
// random timing delays.
//-------------------------------------
#define MT_IA 397
#define MT_LEN 624

class MersenneTwister
{
unsigned int m_buffer[MT_LEN];
int m_index;

public:
MersenneTwister(unsigned int seed);
// Declare noinline so that the function call acts as a compiler barrier:
unsigned int integer() __attribute__((noinline));
};

MersenneTwister::MersenneTwister(unsigned int seed)
{
// Initialize by filling with the seed, then iterating
// the algorithm a bunch of times to shuffle things up.
for (int i = 0; i < MT_LEN; i++)
m_buffer[i] = seed;
m_index = 0;
for (int i = 0; i < MT_LEN * 100; i++)
integer();
}

unsigned int MersenneTwister::integer()
{
// Indices
int i = m_index;
int i2 = m_index + 1; if (i2 >= MT_LEN) i2 = 0; // wrap-around
int j = m_index + MT_IA; if (j >= MT_LEN) j -= MT_LEN; // wrap-around

// Twist
unsigned int s = (m_buffer[i] & 0x80000000) | (m_buffer[i2] & 0x7fffffff);
unsigned int r = m_buffer[j] ^ (s >> 1) ^ ((s & 1) * 0x9908B0DF);
m_buffer[m_index] = r;
m_index = i2;

// Swizzle
r ^= (r >> 11);
r ^= (r << 7) & 0x9d2c5680UL;
r ^= (r << 15) & 0xefc60000UL;
r ^= (r >> 18);
return r;
}


//-------------------------------------
// Main program, as decribed in the post
//-------------------------------------
sem_t beginSema1;
sem_t beginSema2;
sem_t endSema;

int X, Y;
int r1, r2;

void *thread1Func(void *param)
{
MersenneTwister random(1);
for (;;)
{
sem_wait(&beginSema1); // Wait for signal
while (random.integer() % 8 != 0) {} // Random delay

// ----- THE TRANSACTION! -----
X = 1;
#if USE_CPU_FENCE
asm volatile("mfence" ::: "memory"); // Prevent CPU reordering
#else
asm volatile("" ::: "memory"); // Prevent compiler reordering
#endif
r1 = Y;

sem_post(&endSema); // Notify transaction complete
}
return NULL; // Never returns
};

void *thread2Func(void *param)
{
MersenneTwister random(2);
for (;;)
{
sem_wait(&beginSema2); // Wait for signal
while (random.integer() % 8 != 0) {} // Random delay

// ----- THE TRANSACTION! -----
Y = 1;
#if USE_CPU_FENCE
asm volatile("mfence" ::: "memory"); // Prevent CPU reordering
#else
asm volatile("" ::: "memory"); // Prevent compiler reordering
#endif
r2 = X;

sem_post(&endSema); // Notify transaction complete
}
return NULL; // Never returns
};

int main()
{
// Initialize the semaphores
sem_init(&beginSema1, 0, 0);
sem_init(&beginSema2, 0, 0);
sem_init(&endSema, 0, 0);

// Spawn the threads
pthread_t thread1, thread2;
pthread_create(&thread1, NULL, thread1Func, NULL);
pthread_create(&thread2, NULL, thread2Func, NULL);

#if USE_SINGLE_HW_THREAD
// Force thread affinities to the same cpu core.
cpu_set_t cpus;
CPU_ZERO(&cpus);
CPU_SET(0, &cpus);
pthread_setaffinity_np(thread1, sizeof(cpu_set_t), &cpus);
pthread_setaffinity_np(thread2, sizeof(cpu_set_t), &cpus);
#endif

// Repeat the experiment ad infinitum
int detected = 0;
for (int iterations = 1; ; iterations++)
{
// Reset X and Y
X = 0;
Y = 0;
// Signal both threads
sem_post(&beginSema1);
sem_post(&beginSema2);
// Wait for both threads
sem_wait(&endSema);
sem_wait(&endSema);
// Check if there was a simultaneous reorder
if (r1 == 0 && r2 == 0)
{
detected++;
printf("%d reorders detected after %d iterations\n", detected, iterations);
}
}
return 0; // Never returns
}

## 然后编译
gcc -O2 reorder.cpp -o reorder

## 执行
./reorder

相关阅读

micro-k8s-使用

· One min read

背景

遇到错误his is not a valid name for a Kubernetes node, causing node registration to fail.

处理步骤

查看错误:

$ microk8s inspect
WARNING:  This machine's hostname contains capital letters and/or underscores. 
This is not a valid name for a Kubernetes node, causing node registration to fail.
Please change the machine's hostname or refer to the documentation for more details:

遇到这个错误的原因是: hostname 不合法

如何查自己的hostname ?

使用hostname 或者hostnamectl 命令

$ hostname
dai-MS-7B89
$ hostnamectl
Static hostname: dai-MS-7B89
Icon name: computer-desktop
Chassis: desktop
Machine ID: d55c62a250474c459bda9aecc21307a7
Boot ID: e97354108f364004a0775ce12cc57d98
Operating System: Ubuntu 22.04 LTS
Kernel: Linux 5.15.0-56-generic
Architecture: x86-64
Hardware Vendor: Micro-Star International Co., Ltd.
Hardware Model: MS-7B89

我现在的名字是大写还有横杠

修改成myhost

sudo hostnamectl set-hostname  myhost

相关阅读

java 方法签名

· One min read

背景

了解java的签名相关内容

javap 查看签名

javap -s java.lang.String
Compiled from "String.java"
public final class java.lang.String implements java.io.Serializable, java.lang.Comparable<java.lang.String>, java.lang.CharSequence {
static final boolean COMPACT_STRINGS;
descriptor: Z
public static final java.util.Comparator<java.lang.String> CASE_INSENSITIVE_ORDER;
descriptor: Ljava/util/Comparator;
static final byte LATIN1;
descriptor: B
static final byte UTF16;
descriptor: B
public java.lang.String();
descriptor: ()V



public java.lang.String(byte[], int, int, int);
descriptor: ([BIII)V

public java.lang.String(byte[], int);
descriptor: ([BI)V

public java.lang.String(byte[], int, int, java.lang.String) throws java.io.UnsupportedEncodingException;
descriptor: ([BIILjava/lang/String;)V


}

相关阅读

tomcat 编译

· 4 min read

背景

了解tomcat生命周期,了解一个http的生命周期

步骤

  • 1 拉取tomcat 代码
git clone https://github.com/apache/tomcat

相关的编译后的安装目录在${tomcat.source}/build.propertiesfile 里面

  • 2 安装ant

我的是ubuntu所以直接通过包管理安装

sudo apt install ant

  • 3 修改复制build.properties 文件 这里面会有相关的属性,和下载代码相关的路径需要在这里配置
cp build.properties.default  build.properties


我们需要将调试符号编译时生成,如果是一个java程序,则是javac -g , 也就是在编译的时候添加到javac 中. 在tomcat的源代码中的build.xml 中很容易看到compile.debug 这个环境变量

<javac srcdir="java" destdir="${tomcat.classes}"
debug="${compile.debug}" <--! 这里会有compile.debug 环境变量 ->
deprecation="${compile.deprecation}"
release="${compile.release}"
encoding="ISO-8859-1"
includeAntRuntime="true" >
<!-- Uncomment this to show unchecked warnings:
<compilerarg value="-Xlint:unchecked"/>

那么这个环境变量是在哪里控制的呢? 打开 build.properties ,就能看到,所以默认下载下来的tomcat 就是开了-g 选项的,不需要修改

# ----- Build control flags -----
compile.debug=true
  • 4 执行构建命令ant
ant

编译好的相关代码会在 , source_code 就是你的源代码

{source_code}/output/build/bin

切换目录到{source_code}/output/build/bin

./startup.sh 
Using CATALINA_BASE: /home/dai/tomcat/output/build
Using CATALINA_HOME: /home/dai/tomcat/output/build
Using CATALINA_TMPDIR: /home/dai/tomcat/output/build/temp
Using JRE_HOME: /usr
Using CLASSPATH: /home/dai/tomcat/output/build/bin/bootstrap.jar:/home/dai/tomcat/output/build/bin/tomcat-juli.jar
Using CATALINA_OPTS:
Tomcat started.

查看tomcat 的命令 , 就是以下内容:

ps aux | grep tomcat


/usr/bin/java -Djava.util.logging.config.file=/home/dai/tomcat/output/build/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED -classpath /home/dai/tomcat/output/build/bin/bootstrap.jar:/home/dai/tomcat/output/build/bin/tomcat-juli.jar -Dcatalina.base=/home/dai/tomcat/output/build -Dcatalina.home=/home/dai/tomcat/output/build -Djava.io.tmpdir=/home/dai/tomcat/output/build/temp org.apache.catalina.startup.Bootstrap start


请求tomcat

在浏览器输入 http://127.0.0.1:8080/

debug tomcat

断点到main函数

在上面步骤用ps aux | grep "tomcat" 获取执行的命令 , 然后在前面/usr/bin/java 紧接着的地方加上参数-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8000 ,让程序断点在main函数

参数说明:

  • suspend 代表是否暂停
  • address: 指定地址 , 也可以只指定端口,我这里是8000 端口
  • -agentlib:jdwp=transport 协议 ,一般本地用socket 通讯 , 也可以共享内存什么的 。 我这里是dt_socket
/usr/bin/java -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8000   -Djava.util.logging.config.file=/home/dai/tomcat/output/build/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED -classpath /home/dai/tomcat/output/build/bin/bootstrap.jar:/home/dai/tomcat/output/build/bin/tomcat-juli.jar -Dcatalina.base=/home/dai/tomcat/output/build -Dcatalina.home=/home/dai/tomcat/output/build -Djava.io.tmpdir=/home/dai/tomcat/output/build/temp org.apache.catalina.startup.Bootstrap start

jdb 开启调试

jdb  -attach  8000 -sourcepath /home/dai/tomcat/java/

### 在 org.apache.catalina.startup.Bootstrap.main 打断点
main[1] stop in org.apache.catalina.startup.Bootstrap.main
Deferring breakpoint org.apache.catalina.startup.Bootstrap.main.
It will be set after the class is loaded.
#### 使用run开始执行
main[1] run

使用list 列出代码 然后就会断点到main 函数

Breakpoint hit: "thread=main", org.apache.catalina.startup.Bootstrap.main(), line=442 bci=0
442 synchronized (daemonLock) {

main[1] list
438 * @param args Command line arguments to be processed
439 */
440 public static void main(String args[]) {
441
442 => synchronized (daemonLock) {
443 if (daemon == null) {
444 // Don't set daemon until init() has completed
445 Bootstrap bootstrap = new Bootstrap();
446 try {
447 bootstrap.init();
main[1]

servelet 请求路径

http-nio-8080-exec-1[1] where
[1] HelloWorldExample.doGet (HelloWorldExample.java:41)
[2] jakarta.servlet.http.HttpServlet.service (HttpServlet.java:705)
[3] jakarta.servlet.http.HttpServlet.service (HttpServlet.java:814)
[4] org.apache.catalina.core.ApplicationFilterChain.internalDoFilter (ApplicationFilterChain.java:223)
[5] org.apache.catalina.core.ApplicationFilterChain.doFilter (ApplicationFilterChain.java:158)
[6] org.apache.tomcat.websocket.server.WsFilter.doFilter (WsFilter.java:53)
[7] org.apache.catalina.core.ApplicationFilterChain.internalDoFilter (ApplicationFilterChain.java:185)
[8] org.apache.catalina.core.ApplicationFilterChain.doFilter (ApplicationFilterChain.java:158)
[9] org.apache.catalina.filters.HttpHeaderSecurityFilter.doFilter (HttpHeaderSecurityFilter.java:126)
[10] org.apache.catalina.core.ApplicationFilterChain.internalDoFilter (ApplicationFilterChain.java:185)
[11] org.apache.catalina.core.ApplicationFilterChain.doFilter (ApplicationFilterChain.java:158)
[12] org.apache.catalina.core.StandardWrapperValve.invoke (StandardWrapperValve.java:177)
[13] org.apache.catalina.core.StandardContextValve.invoke (StandardContextValve.java:97)
[14] org.apache.catalina.authenticator.AuthenticatorBase.invoke (AuthenticatorBase.java:542)
[15] org.apache.catalina.core.StandardHostValve.invoke (StandardHostValve.java:119)
[16] org.apache.catalina.valves.ErrorReportValve.invoke (ErrorReportValve.java:92)
[17] org.apache.catalina.valves.AbstractAccessLogValve.invoke (AbstractAccessLogValve.java:690)
[18] org.apache.catalina.core.StandardEngineValve.invoke (StandardEngineValve.java:78)
[19] org.apache.catalina.connector.CoyoteAdapter.service (CoyoteAdapter.java:357)
[20] org.apache.coyote.http11.Http11Processor.service (Http11Processor.java:400)
[21] org.apache.coyote.AbstractProcessorLight.process (AbstractProcessorLight.java:65)
[22] org.apache.coyote.AbstractProtocol$ConnectionHandler.process (AbstractProtocol.java:859)
[23] org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun (NioEndpoint.java:1,734)
[24] org.apache.tomcat.util.net.SocketProcessorBase.run (SocketProcessorBase.java:52)
[25] org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1,191)
[26] org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:659)
[27] org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run (TaskThread.java:61)
[28] java.lang.Thread.run (Thread.java:833)

相关阅读

java assert

· One min read

背景

assert 是glibc 一个函数. java也有类似功能,断言是可以快速在测试环境发现问题的功能. 在java里面,assert是一个Statement 也就是一个语句

springboot 请求流程

· 3 min read

背景

了解java里面spring boot 一个http请求的生命周期

tomcat 启动

initialize:108, TomcatWebServer (org.springframework.boot.web.embedded.tomcat)
<init>:104, TomcatWebServer (org.springframework.boot.web.embedded.tomcat)
getTomcatWebServer:440, TomcatServletWebServerFactory (org.springframework.boot.web.embedded.tomcat)
getWebServer:193, TomcatServletWebServerFactory (org.springframework.boot.web.embedded.tomcat)
createWebServer:178, ServletWebServerApplicationContext (org.springframework.boot.web.servlet.context)
onRefresh:158, ServletWebServerApplicationContext (org.springframework.boot.web.servlet.context)
refresh:545, AbstractApplicationContext (org.springframework.context.support)
refresh:143, ServletWebServerApplicationContext (org.springframework.boot.web.servlet.context)
refresh:755, SpringApplication (org.springframework.boot)
refresh:747, SpringApplication (org.springframework.boot)
refreshContext:402, SpringApplication (org.springframework.boot)
run:312, SpringApplication (org.springframework.boot)
main:22, Application

堆栈:

getLanguagesAllList:35, CommonController (com.patpat.mms.mdp.base.core.rest.controller)
invoke:-1, CommonController$$FastClassBySpringCGLIB$$2cf69542 (com.patpat.mms.mdp.base.core.rest.controller)
invoke:218, MethodProxy (org.springframework.cglib.proxy)
invokeJoinpoint:779, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
proceed:163, ReflectiveMethodInvocation (org.springframework.aop.framework)
proceed:750, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
proceed:88, MethodInvocationProceedingJoinPoint (org.springframework.aop.aspectj)
doAround:27, AbstractLogAspect (com.patpat.marketing.common.aspect.log)
invoke0:-1, NativeMethodAccessorImpl (jdk.internal.reflect)
invoke:62, NativeMethodAccessorImpl (jdk.internal.reflect)
invoke:43, DelegatingMethodAccessorImpl (jdk.internal.reflect)
invoke:566, Method (java.lang.reflect)
invokeAdviceMethodWithGivenArgs:644, AbstractAspectJAdvice (org.springframework.aop.aspectj)
invokeAdviceMethod:633, AbstractAspectJAdvice (org.springframework.aop.aspectj)
invoke:70, AspectJAroundAdvice (org.springframework.aop.aspectj)
proceed:186, ReflectiveMethodInvocation (org.springframework.aop.framework)
proceed:750, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
invoke:95, ExposeInvocationInterceptor (org.springframework.aop.interceptor)
proceed:186, ReflectiveMethodInvocation (org.springframework.aop.framework)
proceed:750, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
intercept:692, CglibAopProxy$DynamicAdvisedInterceptor (org.springframework.aop.framework)
getLanguagesAllList:-1, CommonController$$EnhancerBySpringCGLIB$$cea69971 (com.patpat.mms.mdp.base.core.rest.controller)
invoke0:-1, NativeMethodAccessorImpl (jdk.internal.reflect)
invoke:62, NativeMethodAccessorImpl (jdk.internal.reflect)
invoke:43, DelegatingMethodAccessorImpl (jdk.internal.reflect)
invoke:566, Method (java.lang.reflect)
doInvoke:190, InvocableHandlerMethod (org.springframework.web.method.support)
invokeForRequest:138, InvocableHandlerMethod (org.springframework.web.method.support)
invokeAndHandle:105, ServletInvocableHandlerMethod (org.springframework.web.servlet.mvc.method.annotation)
invokeHandlerMethod:878, RequestMappingHandlerAdapter (org.springframework.web.servlet.mvc.method.annotation)
handleInternal:792, RequestMappingHandlerAdapter (org.springframework.web.servlet.mvc.method.annotation)
handle:87, AbstractHandlerMethodAdapter (org.springframework.web.servlet.mvc.method)
doDispatch:1040, DispatcherServlet (org.springframework.web.servlet)
doService:943, DispatcherServlet (org.springframework.web.servlet)
processRequest:1006, FrameworkServlet (org.springframework.web.servlet)
doPost:909, FrameworkServlet (org.springframework.web.servlet)
service:652, HttpServlet (javax.servlet.http)
service:883, FrameworkServlet (org.springframework.web.servlet)
service:733, HttpServlet (javax.servlet.http)
internalDoFilter:227, ApplicationFilterChain (org.apache.catalina.core)
doFilter:162, ApplicationFilterChain (org.apache.catalina.core)
doFilter:53, WsFilter (org.apache.tomcat.websocket.server)
internalDoFilter:189, ApplicationFilterChain (org.apache.catalina.core)
doFilter:162, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:100, RequestContextFilter (org.springframework.web.filter)
doFilter:119, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:189, ApplicationFilterChain (org.apache.catalina.core)
doFilter:162, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:93, FormContentFilter (org.springframework.web.filter)
doFilter:119, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:189, ApplicationFilterChain (org.apache.catalina.core)
doFilter:162, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:97, WebMvcMetricsFilter (org.springframework.boot.actuate.metrics.web.servlet)
doFilter:119, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:189, ApplicationFilterChain (org.apache.catalina.core)
doFilter:162, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:201, CharacterEncodingFilter (org.springframework.web.filter)
doFilter:119, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:189, ApplicationFilterChain (org.apache.catalina.core)
doFilter:162, ApplicationFilterChain (org.apache.catalina.core)
invoke:202, StandardWrapperValve (org.apache.catalina.core)
invoke:97, StandardContextValve (org.apache.catalina.core)
invoke:542, AuthenticatorBase (org.apache.catalina.authenticator)
invoke:143, StandardHostValve (org.apache.catalina.core)
invoke:92, ErrorReportValve (org.apache.catalina.valves)
invoke:78, StandardEngineValve (org.apache.catalina.core)
service:357, CoyoteAdapter (org.apache.catalina.connector)
service:374, Http11Processor (org.apache.coyote.http11)
process:65, AbstractProcessorLight (org.apache.coyote)
process:893, AbstractProtocol$ConnectionHandler (org.apache.coyote)
doRun:1707, NioEndpoint$SocketProcessor (org.apache.tomcat.util.net)
run:49, SocketProcessorBase (org.apache.tomcat.util.net)
runWorker:1128, ThreadPoolExecutor (java.util.concurrent)
run:628, ThreadPoolExecutor$Worker (java.util.concurrent)
run:61, TaskThread$WrappingRunnable (org.apache.tomcat.util.threads)
run:834, Thread (java.lang)

dispatcher servelet

堆栈

doService:911, DispatcherServlet (org.springframework.web.servlet)
processRequest:1006, FrameworkServlet (org.springframework.web.servlet)
doPost:909, FrameworkServlet (org.springframework.web.servlet)
service:652, HttpServlet (javax.servlet.http)
service:883, FrameworkServlet (org.springframework.web.servlet)
service:733, HttpServlet (javax.servlet.http)
internalDoFilter:227, ApplicationFilterChain (org.apache.catalina.core)
doFilter:162, ApplicationFilterChain (org.apache.catalina.core)
doFilter:53, WsFilter (org.apache.tomcat.websocket.server)
internalDoFilter:189, ApplicationFilterChain (org.apache.catalina.core)
doFilter:162, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:100, RequestContextFilter (org.springframework.web.filter)
doFilter:119, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:189, ApplicationFilterChain (org.apache.catalina.core)
doFilter:162, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:93, FormContentFilter (org.springframework.web.filter)
doFilter:119, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:189, ApplicationFilterChain (org.apache.catalina.core)
doFilter:162, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:97, WebMvcMetricsFilter (org.springframework.boot.actuate.metrics.web.servlet)
doFilter:119, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:189, ApplicationFilterChain (org.apache.catalina.core)
doFilter:162, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:201, CharacterEncodingFilter (org.springframework.web.filter)
doFilter:119, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:189, ApplicationFilterChain (org.apache.catalina.core)
doFilter:162, ApplicationFilterChain (org.apache.catalina.core)
invoke:202, StandardWrapperValve (org.apache.catalina.core)
invoke:97, StandardContextValve (org.apache.catalina.core)
invoke:542, AuthenticatorBase (org.apache.catalina.authenticator)
invoke:143, StandardHostValve (org.apache.catalina.core)
invoke:92, ErrorReportValve (org.apache.catalina.valves)
invoke:78, StandardEngineValve (org.apache.catalina.core)
service:357, CoyoteAdapter (org.apache.catalina.connector)
service:374, Http11Processor (org.apache.coyote.http11)
process:65, AbstractProcessorLight (org.apache.coyote)
process:893, AbstractProtocol$ConnectionHandler (org.apache.coyote)
doRun:1707, NioEndpoint$SocketProcessor (org.apache.tomcat.util.net)
run:49, SocketProcessorBase (org.apache.tomcat.util.net)
runWorker:1128, ThreadPoolExecutor (java.util.concurrent)
run:628, ThreadPoolExecutor$Worker (java.util.concurrent)
run:61, TaskThread$WrappingRunnable (org.apache.tomcat.util.threads)
run:834, Thread (java.lang)

相关阅读

javac

· 2 min read

背景

  • 了解java 编译过程
  • 使用java的module调用javac

java的编译命令

在java jdk9 开始,拥有了module 系统 ,jdk里面内部的库也拆分成为不同的module

java的编译前端命令是javac ,实际上调用的是jdk.compiler 这个module下面的类com.sun.tools.javac.Main

也就是说javac 这个命令和 java --module jdk.compiler/com.sun.tools.javac.Main 这个命令是一致的

java前端

列出所有的module


$ java --list-modules
...
jdk.attach@17.0.5
jdk.charsets@17.0.5
jdk.compiler@17.0.5
...

我的jdk现在是jdk17 , 可以看到其中有一个jdk.compiler 的module , 这个就是java编译器前端

使用module 方式调用

先创建一个hello world

vim com/Hello.java

内容如下:

package com;
public class Hello{
public static void main(String [] argc){

System.out.print(argc.length);

}
}

然后使用以下命令编译:

java  --module   jdk.compiler/com.sun.tools.javac.Main  com/Hello.java

获取class 文件:

$tree com
com
├── Hello.class
└── Hello.java

执行这个hello world 的demo:

$ java com.Hello
0

正常执行

相关阅读

xid equal to close_xid

· One min read

背景

线上环境写入clickhouse的时候出现错误xid equal to close_xid , 只报错一次 ,后续就好了

returned error: Code: 999, e.displayText() = DB::Exception: Cannot allocate block number in ZooKeeper: Coordination::Exception: xid equal to close_xid (Session expired) 

排查问题

看了一下pr , 是19年加的pr ,当xid 等于0xffffffff 的时候就抛出异常,防止出现死锁 . 在异常之后的下一次请求,clickhouse会重新zookpeer,然后重置xid ,保证整个链接正常

相关阅读