使用jstack
背景
排查线上问题 ,定位故障线程
使用top
使用top -p PID -H
可以获取对应线程下面的线程以及负载
使用thread
https://arthas.aliyun.com/doc/thread.html
排查线上问题 ,定位故障线程
使用top -p PID -H
可以获取对应线程下面的线程以及负载
https://arthas.aliyun.com/doc/thread.html
Garbage-First简称g1算法,是java目前可选的一个gc算法。
目标: 在一定的软实时性条件下,保证整体的吞吐
算法构成:
The Garbage-First collector achieves these goals via sev- eral techniques. The heap is partitioned into a set of equal- sized heap regions, much like the train cars of the Mature- Object Space collector of Hudson and Moss [22]. However, whereas the remembered sets of the Mature-Object Space collector are unidirectional, recording pointers from older regions to younger but not vice versa, Garbage-First remem- bered sets record pointers from all regions (with some excep- tions, described in sections 2.4 and 4.6). Recording all ref- erences allows an arbitrary set of heap regions to be chosen for collection. A concurrent thread processes log records cre- ated by special mutator write barriers to keep remembered sets up-to-date, allowing shorter collections.
void G1YoungCollector::collect() {
// Do timing/tracing/statistics/pre- and post-logging/verification work not
// directly related to the collection. They should not be accounted for in
// collection work timing.
// The G1YoungGCTraceTime message depends on collector state, so must come after
// determining collector state.
G1YoungGCTraceTime tm(this, _gc_cause);
// JFR
G1YoungGCJFRTracerMark jtm(gc_timer_stw(), gc_tracer_stw(), _gc_cause);
// JStat/MXBeans
G1MonitoringScope ms(monitoring_support(),
false /* full_gc */,
collector_state()->in_mixed_phase() /* all_memory_pools_affected */);
// Create the heap printer before internal pause timing to have
// heap information printed as last part of detailed GC log.
G1HeapPrinterMark hpm(_g1h);
// Young GC internal pause timing
G1YoungGCNotifyPauseMark npm(this);
// Verification may use the workers, so they must be set up before.
// Individual parallel phases may override this.
set_young_collection_default_active_worker_threads();
// Wait for root region scan here to make sure that it is done before any
// use of the STW workers to maximize cpu use (i.e. all cores are available
// just to do that).
wait_for_root_region_scanning();
G1YoungGCVerifierMark vm(this);
{
// Actual collection work starts and is executed (only) in this scope.
// Young GC internal collection timing. The elapsed time recorded in the
// policy for the collection deliberately elides verification (and some
// other trivial setup above).
policy()->record_young_collection_start();
calculate_collection_set(jtm.evacuation_info(), _target_pause_time_ms);
G1RedirtyCardsQueueSet rdcqs(G1BarrierSet::dirty_card_queue_set().allocator());
G1PreservedMarksSet preserved_marks_set(workers()->active_workers());
G1ParScanThreadStateSet per_thread_states(_g1h,
&rdcqs,
&preserved_marks_set,
workers()->active_workers(),
collection_set()->young_region_length(),
collection_set()->optional_region_length(),
&_evac_failure_regions);
pre_evacuate_collection_set(jtm.evacuation_info(), &per_thread_states);
bool may_do_optional_evacuation = collection_set()->optional_region_length() != 0;
// Actually do the work...
evacuate_initial_collection_set(&per_thread_states, may_do_optional_evacuation);
if (may_do_optional_evacuation) {
evacuate_optional_collection_set(&per_thread_states);
}
post_evacuate_collection_set(jtm.evacuation_info(), &per_thread_states);
// Refine the type of a concurrent mark operation now that we did the
// evacuation, eventually aborting it.
_concurrent_operation_is_full_mark = policy()->concurrent_operation_is_full_mark("Revise IHOP");
// Need to report the collection pause now since record_collection_pause_end()
// modifies it to the next state.
jtm.report_pause_type(collector_state()->young_gc_pause_type(_concurrent_operation_is_full_mark));
policy()->record_young_collection_end(_concurrent_operation_is_full_mark, evacuation_failed());
}
TASKQUEUE_STATS_ONLY(print_taskqueue_stats());
TASKQUEUE_STATS_ONLY(reset_taskqueue_stats());
}
真正复制的代码
evacuate_live_objects(
MAYBE_INLINE_EVACUATION
void G1ParScanThreadState::dispatch_task(ScannerTask task) {
verify_task(task);
if (task.is_narrow_oop_ptr()) {
do_oop_evac(task.to_narrow_oop_ptr());
} else if (task.is_oop_ptr()) { //oop 复制
do_oop_evac(task.to_oop_ptr());
} else {
do_partial_array(task.to_partial_array_task());
}
}
堆栈:
Thread 23 "GC Thread#4" hit Breakpoint 1, G1ParScanThreadState::do_copy_to_survivor_space (this=0x7fff7c000d90, region_attr=..., old=0x716809d28, old_mark=...) at /home/dai/jdk/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp:443
443 assert(region_attr.is_in_cset(),
(gdb) bt
#0 G1ParScanThreadState::do_copy_to_survivor_space (this=0x7fff7c000d90, region_attr=..., old=0x716809d28, old_mark=...) at /home/dai/jdk/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp:443
#1 0x00007ffff64ab3f6 in G1ParScanThreadState::copy_to_survivor_space (this=0x7fff7c000d90, region_attr=..., old=0x716809d28, old_mark=...)
at /home/dai/jdk/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp:555
#2 0x00007ffff64de15e in G1ParCopyClosure<(G1Barrier)0, false>::do_oop_work<oopDesc*> (this=0x7fff7c001478, p=0x7ffff02e1cc8) at /home/dai/jdk/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp:240
#3 0x00007ffff64dcbc3 in G1ParCopyClosure<(G1Barrier)0, false>::do_oop (this=0x7fff7c001478, p=0x7ffff02e1cc8) at /home/dai/jdk/src/hotspot/share/gc/g1/g1OopClosures.hpp:167
#4 0x00007ffff6546dd8 in chunk_oops_do (f=0x7fff7c001478, chunk=0x7ffff02e1cb0, chunk_top=0x7ffff02e1cd0 "\350\034\200\026\a") at /home/dai/jdk/src/hotspot/share/runtime/handles.cpp:100
#5 0x00007ffff6546e23 in HandleArea::oops_do (this=0x7ffff02e1c30, f=0x7fff7c001478) at /home/dai/jdk/src/hotspot/share/runtime/handles.cpp:108
#6 0x00007ffff6d85dd4 in Thread::oops_do_no_frames (this=0x7ffff02e1160, f=0x7fff7c001478, cf=0x7fff7c001520) at /home/dai/jdk/src/hotspot/share/runtime/thread.cpp:550
#7 0x00007ffff6d8a513 in JavaThread::oops_do_no_frames (this=0x7ffff02e1160, f=0x7fff7c001478, cf=0x7fff7c001520) at /home/dai/jdk/src/hotspot/share/runtime/thread.cpp:1968
#8 0x00007ffff6d85e28 in Thread::oops_do (this=0x7ffff02e1160, f=0x7fff7c001478, cf=0x7fff7c001520) at /home/dai/jdk/src/hotspot/share/runtime/thread.cpp:580
#9 0x00007ffff6d91359 in ParallelOopsDoThreadClosure::do_thread (this=0x7fff87dfaa00, t=0x7ffff02e1160) at /home/dai/jdk/src/hotspot/share/runtime/thread.cpp:3620
#10 0x00007ffff6d8c40b in Threads::possibly_parallel_threads_do (is_par=true, tc=0x7fff87dfaa00) at /home/dai/jdk/src/hotspot/share/runtime/thread.cpp:2545
#11 0x00007ffff6d8eac8 in Threads::possibly_parallel_oops_do (is_par=true, f=0x7fff7c001478, cf=0x7fff7c001520) at /home/dai/jdk/src/hotspot/share/runtime/thread.cpp:3626
#12 0x00007ffff64dea53 in G1RootProcessor::process_java_roots (this=0x7fffc9723df0, closures=0x7fff7c001470, phase_times=0x7fffb8001380, worker_id=1)
at /home/dai/jdk/src/hotspot/share/gc/g1/g1RootProcessor.cpp:183
#13 0x00007ffff64de78e in G1RootProcessor::evacuate_roots (this=0x7fffc9723df0, pss=0x7fff7c000d90, worker_id=1) at /home/dai/jdk/src/hotspot/share/gc/g1/g1RootProcessor.cpp:60
#14 0x00007ffff64f06b8 in G1EvacuateRegionsTask::scan_roots (this=0x7fffc9723f50, pss=0x7fff7c000d90, worker_id=1) at /home/dai/jdk/src/hotspot/share/gc/g1/g1YoungCollector.cpp:706
#15 0x00007ffff64f0632 in G1EvacuateRegionsBaseTask::work (this=0x7fffc9723f50, worker_id=1) at /home/dai/jdk/src/hotspot/share/gc/g1/g1YoungCollector.cpp:693
#16 0x00007ffff6e8bb7c in WorkerTaskDispatcher::worker_run_task (this=0x7ffff00a4c88) at /home/dai/jdk/src/hotspot/share/gc/shared/workerThread.cpp:67
#17 0x00007ffff6e8c074 in WorkerThread::run (this=0x7fffb800df30) at /home/dai/jdk/src/hotspot/share/gc/shared/workerThread.cpp:159
#18 0x00007ffff6d8557f in Thread::call_run (this=0x7fffb800df30) at /home/dai/jdk/src/hotspot/share/runtime/thread.cpp:358
#19 0x00007ffff6acc1e7 in thread_native_entry (thread=0x7fffb800df30) at /home/dai/jdk/src/hotspot/os/linux/os_linux.cpp:705
#20 0x00007ffff7c94ac3 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
#21 0x00007ffff7d26a40 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
内存复制:
static void pd_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
#ifdef AMD64
switch (count) {
case 8: to[7] = from[7];
case 7: to[6] = from[6];
case 6: to[5] = from[5];
case 5: to[4] = from[4];
case 4: to[3] = from[3];
case 3: to[2] = from[2];
case 2: to[1] = from[1];
case 1: to[0] = from[0];
case 0: break;
default:
(void)memcpy(to, from, count * HeapWordSize);
break;
}
#else
// Includes a zero-count check.
intx temp;
__asm__ volatile(" testl %6,%6 ;"
" jz 3f ;"
" cmpl $32,%6 ;"
" ja 2f ;"
" subl %4,%1 ;"
"1: movl (%4),%3 ;"
" movl %7,(%5,%4,1);"
" addl $4,%0 ;"
" subl $1,%2 ;"
" jnz 1b ;"
" jmp 3f ;"
"2: rep; smovl ;"
"3: nop "
: "=S" (from), "=D" (to), "=c" (count), "=r" (temp)
: "0" (from), "1" (to), "2" (count), "3" (temp)
: "memory", "cc");
#endif // AMD64
}
并发标记: D:\jdk\src\hotspot\share\gc\g1\g1ConcurrentMark.inline.hpp
inline bool G1ConcurrentMark::mark_in_bitmap(uint const worker_id, oop const obj) {
HeapRegion* const hr = _g1h->heap_region_containing(obj);
if (hr->obj_allocated_since_marking_start(obj)) {
return false;
}
// Some callers may have stale objects to mark above TAMS after humongous reclaim.
// Can't assert that this is a valid object at this point, since it might be in the process of being copied by another thread.
assert(!hr->is_continues_humongous(), "Should not try to mark object " PTR_FORMAT " in Humongous continues region %u above TAMS " PTR_FORMAT, p2i(obj), hr->hrm_index(), p2i(hr->top_at_mark_start()));
bool success = _mark_bitmap.par_mark(obj);
if (success) {
add_to_liveness(worker_id, obj, obj->size());
}
return success;
}
分配内存:
HeapWord*
G1CollectedHeap::mem_allocate(size_t word_size,
bool* gc_overhead_limit_was_exceeded) {
assert_heap_not_locked_and_not_at_safepoint();
if (is_humongous(word_size)) {
return attempt_allocation_humongous(word_size);
}
size_t dummy = 0;
return attempt_allocation(word_size, word_size, &dummy);
}
product(uint, GCCardSizeInBytes, 512, \
"Card table entry size (in bytes) for card based collectors") \
range(128, NOT_LP64(512) LP64_ONLY(1024)) \
constraint(GCCardSizeInBytesConstraintFunc,AtParse)
cartable 为什么是512
_card_size = GCCardSizeInBytes;
_card_shift = log2i_exact(_card_size);
_card_size_in_words = _card_size / sizeof(HeapWord);
template <DecoratorSet decorators, typename BarrierSetT>
template <typename T>
inline void G1BarrierSet::AccessBarrier<decorators, BarrierSetT>::
oop_store_not_in_heap(T* addr, oop new_value) {
// Apply SATB barriers for all non-heap references, to allow
// concurrent scanning of such references.
G1BarrierSet *bs = barrier_set_cast<G1BarrierSet>(BarrierSet::barrier_set());
bs->write_ref_field_pre<decorators>(addr);
Raw::oop_store(addr, new_value);
}
写入barrier逻辑
void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Address dst, Register val, Register tmp1, Register tmp2, Register tmp3) {
bool in_heap = (decorators & IN_HEAP) != 0;
bool as_normal = (decorators & AS_NORMAL) != 0;
bool needs_pre_barrier = as_normal;
bool needs_post_barrier = val != noreg && in_heap;
Register rthread = LP64_ONLY(r15_thread) NOT_LP64(rcx);
// flatten object address if needed
// We do it regardless of precise because we need the registers
if (dst.index() == noreg && dst.disp() == 0) {
if (dst.base() != tmp1) {
__ movptr(tmp1, dst.base());
}
} else {
__ lea(tmp1, dst);
}
#ifndef _LP64
InterpreterMacroAssembler *imasm = static_cast<InterpreterMacroAssembler*>(masm);
#endif
NOT_LP64(__ get_thread(rcx));
NOT_LP64(imasm->save_bcp());
if (needs_pre_barrier) {
g1_write_barrier_pre(masm /*masm*/,
tmp1 /* obj */,
tmp2 /* pre_val */,
rthread /* thread */,
tmp3 /* tmp */,
val != noreg /* tosca_live */,
false /* expand_call */);
}
if (val == noreg) {
BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp1, 0), val, noreg, noreg, noreg);
} else {
Register new_val = val;
if (needs_post_barrier) {
// G1 barrier needs uncompressed oop for region cross check.
if (UseCompressedOops) {
new_val = tmp2;
__ movptr(new_val, val);
}
}
BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp1, 0), val, noreg, noreg, noreg);
if (needs_post_barrier) {
g1_write_barrier_post(masm /*masm*/,
tmp1 /* store_adr */,
new_val /* new_val */,
rthread /* thread */,
tmp3 /* tmp */,
tmp2 /* tmp2 */);
}
}
NOT_LP64(imasm->restore_bcp());
}
hread 2 "java" hit Breakpoint 1, 0x00007ffff6fa66d8 in G1BarrierSetAssembler::oop_store_at(MacroAssembler*, unsigned long, BasicType, Address, Register, Register, Register, Register) ()
from /usr/lib/jvm/java-21-openjdk-amd64/lib/server/libjvm.so
(gdb) bt
#0 0x00007ffff6fa66d8 in G1BarrierSetAssembler::oop_store_at(MacroAssembler*, unsigned long, BasicType, Address, Register, Register, Register, Register) ()
from /usr/lib/jvm/java-21-openjdk-amd64/lib/server/libjvm.so
#1 0x00007ffff7482012 in ModRefBarrierSetAssembler::store_at(MacroAssembler*, unsigned long, BasicType, Address, Register, Register, Register, Register) ()
from /usr/lib/jvm/java-21-openjdk-amd64/lib/server/libjvm.so
#2 0x00007ffff740992a in MacroAssembler::store_heap_oop(Address, Register, Register, Register, Register, unsigned long) ()
from /usr/lib/jvm/java-21-openjdk-amd64/lib/server/libjvm.so
#3 0x00007ffff77506ec in TemplateTable::aastore() ()
from /usr/lib/jvm/java-21-openjdk-amd64/lib/server/libjvm.so
#4 0x00007ffff7746b47 in Template::generate(InterpreterMacroAssembler*) ()
from /usr/lib/jvm/java-21-openjdk-amd64/lib/server/libjvm.so
#5 0x00007ffff7736a0c in TemplateInterpreterGenerator::generate_and_dispatch(Template*, TosState) ()
from /usr/lib/jvm/java-21-openjdk-amd64/lib/server/libjvm.so
#6 0x00007ffff77427f6 in TemplateInterpreterGenerator::set_vtos_entry_points(Template*, unsigned char*&, unsigned char*&, unsigned char*&, unsigned char*&, unsigned char*&, unsigned char*&, unsigned char*&, unsigned char*&, unsigned char*&) () from /usr/lib/jvm/java-21-openjdk-amd64/lib/server/libjvm.so
#7 0x00007ffff77370d7 in TemplateInterpreterGenerator::set_entry_points(Bytecodes::Code) () from /usr/lib/jvm/java-21-openjdk-amd64/lib/server/libjvm.so
#8 0x00007ffff773855b in TemplateInterpreterGenerator::generate_all() ()
--Type <RET> for more, q to quit, c to continue without paging--
from /usr/lib/jvm/java-21-openjdk-amd64/lib/server/libjvm.so
#9 0x00007ffff7735d45 in TemplateInterpreter::initialize_code() () from /usr/lib/jvm/java-21-openjdk-amd64/lib/server/libjvm.so
#10 0x00007ffff70f0007 in interpreter_init_code() () from /usr/lib/jvm/java-21-openjdk-amd64/lib/server/libjvm.so
#11 0x00007ffff70cc117 in init_globals2() () from /usr/lib/jvm/java-21-openjdk-amd64/lib/server/libjvm.so
#12 0x00007ffff7777839 in Threads::create_vm(JavaVMInitArgs*, bool*) () from /usr/lib/jvm/java-21-openjdk-amd64/lib/server/libjvm.so
#13 0x00007ffff719c702 in JNI_CreateJavaVM () from /usr/lib/jvm/java-21-openjdk-amd64/lib/server/libjvm.so
#14 0x00007ffff7f81123 in JavaMain () from /usr/lib/jvm/java-21-openjdk-amd64/bin/../lib/libjli.so
#15 0x00007ffff7f84f0d in ThreadJavaMain () from /usr/lib/jvm/java-21-openjdk-amd64/bin/../lib/libjli.so
#16 0x00007ffff7e233ec in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:444
#17 0x00007ffff7ea3a4c in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
使用k8s 搭建redis集群
root@redis-app-0:/data# redis-cli
127.0.0.1:6379> info cluster
# Cluster
cluster_enabled:1
127.0.0.1:6379> cluster meet 10.42.0.35 6379
OK
127.0.0.1:6379> cluster meet 10.42.0.36 6379
OK
127.0.0.1:6379> cluster meet 10.42.0.37 6379
OK
127.0.0.1:6379> cluster meet 10.42.0.38 6379
OK
127.0.0.1:6379> cluster meet 10.42.0.39 6379
OK
查看节点
27.0.0.1:6379> cluster nodes
f8d5dd6aef17c622f541ade32a95430421606f6c 10.42.0.39:6379 master - 0 1673791234512 0 connected
76af8c3c32cf535a3733ce75db2c3c6719c644fc 10.42.0.38:6379 master - 0 1673791234512 4 connected
7f803ec0f21e4382bb773285fd40286069b26075 10.42.0.36:6379 master - 0 1673791235012 2 connected
c48e86d680b74df9c70cb7369201fb2cbd8650be 10.42.0.34:6379 myself,master - 0 0 5 connected
3ab965513f345444689cdeb7358c51263772f454 10.42.0.35:6379 master - 0 1673791233512 1 connected
8e256e1614cf9f330404693b6f18785da5794fbc 10.42.0.37:6379 master - 0 1673791234011 3 connected
127.0.0.1:6379>
分配槽位:
10.42.0.39:6379> cluster nodes
f8d5dd6aef17c622f541ade32a95430421606f6c 10.42.0.39:6379 myself,slave 76af8c3c32cf535a3733ce75db2c3c6719c644fc 0 0 0 connected
7f803ec0f21e4382bb773285fd40286069b26075 10.42.0.36:6379 master - 0 1673791666954 2 connected
8e256e1614cf9f330404693b6f18785da5794fbc 10.42.0.37:6379 slave 7f803ec0f21e4382bb773285fd40286069b26075 0 1673791668456 3 connected
76af8c3c32cf535a3733ce75db2c3c6719c644fc 10.42.0.38:6379 master - 0 1673791667955 4 connected
3ab965513f345444689cdeb7358c51263772f454 10.42.0.35:6379 slave c48e86d680b74df9c70cb7369201fb2cbd8650be 0 1673791668955 5 connected
c48e86d680b74df9c70cb7369201fb2cbd8650be 10.42.0.34:6379 master - 0 1673791666954 5 connected
10.42.0.39:6379> redis-cli -h 10.42.0.34 -p 6379 cluster addslots {0..5461}
(error) ERR unknown command 'redis-cli'
10.42.0.39:6379> exit
root@redis-app-0:/data# redis-cli -h 10.42.0.34 -p 6379 cluster addslots {0..5461}
OK
root@redis-app-0:/data# redis-cli -h 10.42.0.36 -p 6379 cluster addslots {5462..10922}
OK
root@redis-app-0:/data# redis-cli -h 10.42.0.38 -p 6379 cluster addslots {10923..16383}
搭建结果:
127.0.0.1:6379> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:5
cluster_my_epoch:5
cluster_stats_messages_sent:3134
cluster_stats_messages_received:3134
线上环境请求clickhouse 400 bad request
线上clickhouse导出的是http端口
线上java client抛出400异常:
ru.yandex.clickhouse.except.ClickHouseException: ClickHouse exception, code: 400, host: internal-LB-clickhouse-write-intranet-429192233.us-west-2.elb.amazonaws.com, port: 8123; HTTP/1.1 400 Bad Request
at ru.yandex.clickhouse.except.ClickHouseExceptionSpecifier.specify(ClickHouseExceptionSpecifier.java:60)
at ru.yandex.clickhouse.except.ClickHouseExceptionSpecifier.specify(ClickHouseExceptionSpecifier.java:26)
at ru.yandex.clickhouse.ClickHouseStatementImpl.checkForErrorAndThrow(ClickHouseStatementImpl.java:1080)
at ru.yandex.clickhouse.ClickHouseStatementImpl.getInputStream(ClickHouseStatementImpl.java:770)
at ru.yandex.clickhouse.ClickHouseStatementImpl.getLastInputStream(ClickHouseStatementImpl.java:693)
Caused by: java.lang.IllegalStateException: HTTP/1.1 400 Bad Request
at ru.yandex.clickhouse.ClickHouseStatementImpl.checkForErrorAndThrow(ClickHouseStatementImpl.java:1080)
at ru.yandex.clickhouse.ClickHouseStatementImpl.getInputStream(ClickHouseStatementImpl.java:770)
at ru.yandex.clickhouse.ClickHouseStatementImpl.getLastInputStream(ClickHouseStatementImpl.java:693)
at ru.yandex.clickhouse.ClickHouseStatementImpl.executeQuery(ClickHouseStatementImpl.java:341)
at ru.yandex.clickhouse.ClickHouseStatementImpl.executeQuery(ClickHouseStatementImpl.java:326)
打开clickhouse日志,发现有以下报错:
2023.01.12 09:24:26.187479 [ 205027 ] {65179d49-ea6e-4a15-b13b-16d8378cfe29} <Error> executeQuery: Code: 62, e.displayText() = DB::Exception: Syntax error: failed at position 72 ('Client'): Client as DEFAULT_VALUE, Application name as DESCRIPTION union all select CustomHttpHeaders as NAME, toInt32(0) as MAX_LEN, as DEFAULT_VALUE, Custom HTTP heade. Expected one of: UNION, LIMIT, WHERE, WINDOW, end of query, HAVING, GROUP BY, INTO OUTFILE, OFFSET, PREWHERE, Comma, ORDER BY, SETTINGS, FROM, FORMAT, WITH, token (version 21.3.3.14 (official build)) (from 172.31.42.57:23878) (in query: select ApplicationName as NAME, toInt32(0) as MAX_LEN, ClickHouse Java Client as DEFAULT_VALUE, Application name as DESCRIPTION union all select CustomHttpHeaders as NAME, toInt32(0) as MAX_LEN, as DEFAULT_VALUE, Custom HTTP headers as DESCRIPTION union all select CustomHttpParameters as NAME, toInt32(0) as MAX_LEN, as DEFAULT_VALUE, Customer HTTP query parameters as DESCRIPTION), Stack trace (when copying this message, always include the lines below):
最后在github上找到相关issue: https://github.com/dbeaver/dbeaver/issues/16885 https://github.com/ClickHouse/clickhouse-jdbc/pull/930
发现是clickhouse的jdbc 包的sql错了
ClickHouse Java Client as DEFAULT_VALUE 应该改为 'ClickHouse Java Client' as DEFAULT_VALUE
我们用的jdbc包是0.3.2
<dependency>
<groupId>ru.yandex.clickhouse</groupId>
<artifactId>clickhouse-jdbc</artifactId>
<version>0.3.2</version>
</dependency>
将clickhouse jdbc 包改成0.3.2-patch-1 即可.
其实可以用更加新的包,自己选择吧.
测试环境有个old generation 非常占用内存.所以需要排查
同事压测的时候,发现old generation 占用内存非常大
例子是下图的样子:

相关配置:
g1使用jamp命令将java的内存dump出来
jmap -dump:format=b,,live,file=<file-path> <pid>
然后去下载mat工具下载地址
安装之后打开,点击Dominator Tree:

就可以看到对象以及大小

可以看到有一个900m大小的HashSet , 这是一个去重的set , 每次都会往这里塞入设备id ,当循环结束,会自动不会再被引用,然后会被gc回收.
这不是内存泄漏,而是一个有1kw 数据的的大set ,也就是一个大对象
我们找运维调大了最大的堆内存,问题解决
后续优化: 后续我们打算不使用HashSet 塞字符串去重,而是用布隆过滤器去重
排查一个gc问题的时候想到需要了解java的对象大小
举例这样创建一个1099 的对象会占用多少个字节呢?
那如果是一个特定的对象NumClass
public class NumClass{
public int num1 ;
public int num2 ;
}
那样创建NunClass[] 又占用多少字节呢?
## 这样 的array占用多少字节呢?
Object[] array = new Object[10245] ;
## 这样 的array占用多少字节呢?
Object[] array = new NumClass[10245] ;
结论是两者占用的字节是一样的
先上最简单的new Object的代码,在这个例子里面: 创建了一个长度是10245的对象数组
package com;
public class Hello{
public static volatile Object[] arr ;
public static void main(String [] argv){
arr = new Object[10245]; // 创建一个对象数组 , 数组也是一个对象 , 那么这个对象有多大呢?
arr[1] = "hihi";
}
}
实际上是在64位机器上,没有开启指针压缩的情况下是: 8+ 4 + 10245*8个字节长度
oop 是指针oopDesc* 的别名
typedef class oopDesc* oop;
typedef class instanceOopDesc* instanceOop;
typedef class arrayOopDesc* arrayOop;
typedef class objArrayOopDesc* objArrayOop;
typedef class typeArrayOopDesc* typeArrayOop;
+-----------++----------++-------++------+
| || || || |
| || || || |
| MarkWord || length || oop || oop |
+-----------++----------++-------++------+ repeat 10254 次
核心函数:
jol\jol-core\src\main\java\org\openjdk\jol\layouters\CurrentLayouter.java
@Override
public ClassLayout layout(ClassData data) {
VirtualMachine vm = VM.current();
if (data.isArray()) {
// special case of arrays
int base = vm.arrayBaseOffset(data.arrayComponentType());
int scale = vm.arrayIndexScale(data.arrayComponentType());
long instanceSize = MathUtil.align(base + data.arrayLength() * scale, vm.objectAlignment());
SortedSet<FieldLayout> result = new TreeSet<>();
result.add(new FieldLayout(FieldData.create(data.arrayClass(), "<elements>", data.arrayComponentType()), base, scale * data.arrayLength()));
return ClassLayout.create(data, result, CURRENT, instanceSize, false);
}
Collection<FieldData> fields = data.fields();
SortedSet<FieldLayout> result = new TreeSet<>();
for (FieldData f : fields) {
result.add(new FieldLayout(f, vm.fieldOffset(f.refField()), vm.sizeOfField(f.typeClass())));
}
long instanceSize;
if (result.isEmpty()) {
instanceSize = vm.objectHeaderSize();
} else {
FieldLayout f = result.last();
instanceSize = f.offset() + f.size();
// TODO: This calculation is incorrect if there is a trailing @Contended field, or the instance is @Contended
}
instanceSize = MathUtil.align(instanceSize, vm.objectAlignment());
return ClassLayout.create(data, result, CURRENT, instanceSize, true);
}
static int length_offset_in_bytes() {
return UseCompressedClassPointers ? klass_gap_offset_in_bytes() :
sizeof(arrayOopDesc);
}
创建一个数组
(gdb) bt
#0 arrayOopDesc::length_offset_in_bytes () at /var/jdk/src/hotspot/share/oops/arrayOop.hpp:83
#1 0x00007f93c2fdc06e in arrayOopDesc::length_addr_impl (obj_ptr=0x7162010c0) at /var/jdk/src/hotspot/share/oops/arrayOop.hpp:67
#2 0x00007f93c2fdc0ba in arrayOopDesc::length (this=0x7162010c0) at /var/jdk/src/hotspot/share/oops/arrayOop.hpp:114
#3 0x00007f93c3239521 in arrayOopDesc::is_within_bounds (this=0x7162010c0, index=10) at /var/jdk/src/hotspot/share/oops/arrayOop.hpp:110
#4 0x00007f93c3239690 in typeArrayOopDesc::byte_at_addr (this=0x7162010c0, which=10) at /var/jdk/src/hotspot/share/oops/typeArrayOop.inline.hpp:48
#5 0x00007f93c323972d in typeArrayOopDesc::byte_at_put (this=0x7162010c0, which=10, contents=112 'p') at /var/jdk/src/hotspot/share/oops/typeArrayOop.inline.hpp:96
#6 0x00007f93c389e259 in java_lang_String::create_from_unicode (unicode=0x7f93bc037c88, length=33, __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/javaClasses.cpp:300
#7 0x00007f93c3f7b91d in StringTable::do_intern (string_or_null_h=..., name=0x7f93bc037c88, len=33, hash=2694772907, __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/stringTable.cpp:347
#8 0x00007f93c3f7b87e in StringTable::intern (string_or_null_h=..., name=0x7f93bc037c88, len=33, __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/stringTable.cpp:336
#9 0x00007f93c3f7b5b0 in StringTable::intern (symbol=0x7f93c0018d38, __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/stringTable.cpp:296
#10 0x00007f93c35740b5 in ConstantPool::uncached_string_at (this=0x7f938c02e0a0, which=250, __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/oops/constantPool.cpp:1171
#11 0x00007f93c36a19cd in fieldDescriptor::string_initial_value (this=0x7f93c2bd3a68, __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/runtime/fieldDescriptor.cpp:103
#12 0x00007f93c389ff2d in initialize_static_string_field (fd=0x7f93c2bd3a68, mirror=..., __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/javaClasses.cpp:809
#13 0x00007f93c38a0444 in initialize_static_field (fd=0x7f93c2bd3a68, mirror=..., __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/javaClasses.cpp:866
#14 0x00007f93c3869f51 in InstanceKlass::do_local_static_fields (this=0x8000431a0, f=0x7f93c38a0365 <initialize_static_field(fieldDescriptor*, Handle, JavaThread*)>, mirror=..., __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/oops/instanceKlass.cpp:1672
#15 0x00007f93c38a08d5 in java_lang_Class::initialize_mirror_fields (k=0x8000431a0, mirror=..., protection_domain=..., classData=..., __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/javaClasses.cpp:930
#16 0x00007f93c38a10d1 in java_lang_Class::create_mirror (k=0x8000431a0, class_loader=..., module=..., protection_domain=..., classData=..., __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/javaClasses.cpp:1035
#17 0x00007f93c34c6144 in ClassFileParser::fill_instance_klass (this=0x7f93c2bd3dd0, ik=0x8000431a0, changed_by_loadhook=false, cl_inst_info=..., __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/classFileParser.cpp:5426
#18 0x00007f93c34c532e in ClassFileParser::create_instance_klass (this=0x7f93c2bd3dd0, changed_by_loadhook=false, cl_inst_info=..., __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/classFileParser.cpp:5255
#19 0x00007f93c3b554d1 in KlassFactory::create_from_stream (stream=0x7f93bc036fb0, name=0x7f93c00001f8, loader_data=0x7f93bc121170, cl_info=..., __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/klassFactory.cpp:202
#20 0x00007f93c34d86e9 in ClassLoader::load_class (name=0x7f93c00001f8, search_append_only=false, __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/classLoader.cpp:1231
#21 0x00007f93c4000806 in SystemDictionary::load_instance_class_impl (class_name=0x7f93c00001f8, class_loader=..., __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/systemDictionary.cpp:1289
#22 0x00007f93c4000ba3 in SystemDictionary::load_instance_class (name_hash=2036240099, name=0x7f93c00001f8, class_loader=..., __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/systemDictionary.cpp:1354
#23 0x00007f93c3ffeca9 in SystemDictionary::resolve_instance_class_or_null (name=0x7f93c00001f8, class_loader=..., protection_domain=..., __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/systemDictionary.cpp:723
#24 0x00007f93c3ffd82e in SystemDictionary::resolve_instance_class_or_null_helper (class_name=0x7f93c00001f8, class_loader=..., protection_domain=..., __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/systemDictionary.cpp:294
#25 0x00007f93c3ffd6d4 in SystemDictionary::resolve_or_null (class_name=0x7f93c00001f8, class_loader=..., protection_domain=..., __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/systemDictionary.cpp:277
#26 0x00007f93c3ffd617 in SystemDictionary::resolve_or_fail (class_name=0x7f93c00001f8, class_loader=..., protection_domain=..., throw_error=true, __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/systemDictionary.cpp:263
#27 0x00007f93c32b8d98 in SystemDictionary::resolve_or_fail (class_name=0x7f93c00001f8, throw_error=true, __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/systemDictionary.hpp:100
#28 0x00007f93c40dca98 in vmClasses::resolve (id=vmClassID::Throwable_klass_knum, __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/vmClasses.cpp:99
#29 0x00007f93c40dcb96 in vmClasses::resolve_until (limit_id=vmClassID::SoftReference_klass_knum, start_id=@0x7f93c2bd48f0: vmClassID::Cloneable_klass_knum, __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/vmClasses.cpp:108
#30 0x00007f93c40dd59a in vmClasses::resolve_through (last_id=vmClassID::Reference_klass_knum, start_id=@0x7f93c2bd48f0: vmClassID::Cloneable_klass_knum, __the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/vmClasses.hpp:64
#31 0x00007f93c40dce23 in vmClasses::resolve_all (__the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/vmClasses.cpp:168
#32 0x00007f93c4001ab2 in SystemDictionary::initialize (__the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/classfile/systemDictionary.cpp:1655
#33 0x00007f93c40812fb in Universe::genesis (__the_thread__=0x7f93bc028fa0) at /var/jdk/src/hotspot/share/memory/universe.cpp:335
#34 0x00007f93c408378f in universe2_init () at /var/jdk/src/hotspot/share/memory/universe.cpp:937
#35 0x00007f93c3863d8a in init_globals () at /var/jdk/src/hotspot/share/runtime/init.cpp:132
#36 0x00007f93c404a1ca in Threads::create_vm (args=0x7f93c2bd4d50, canTryAgain=0x7f93c2bd4c5b) at /var/jdk/src/hotspot/share/runtime/thread.cpp:2843
#37 0x00007f93c396f43b in JNI_CreateJavaVM_inner (vm=0x7f93c2bd4da8, penv=0x7f93c2bd4db0, args=0x7f93c2bd4d50) at /var/jdk/src/hotspot/share/prims/jni.cpp:3613
#38 0x00007f93c396f787 in JNI_CreateJavaVM (vm=0x7f93c2bd4da8, penv=0x7f93c2bd4db0, args=0x7f93c2bd4d50) at /var/jdk/src/hotspot/share/prims/jni.cpp:3701
#39 0x00007f93c50e6a6a in InitializeJVM (pvm=0x7f93c2bd4da8, penv=0x7f93c2bd4db0, ifn=0x7f93c2bd4e00) at /var/jdk/src/java.base/share/native/libjli/java.c:1459
#40 0x00007f93c50e35ec in JavaMain (_args=0x7ffedd44e1a0) at /var/jdk/src/java.base/share/native/libjli/java.c:411
#41 0x00007f93c50ea5ec in ThreadJavaMain (args=0x7ffedd44e1a0) at /var/jdk/src/java.base/unix/native/libjli/java_md.c:651
#42 0x00007f93c4f45b43 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
#43 0x00007f93c4fd6bb4 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:100
分配数组大小:
static int array_size(int length) {
const uint OopsPerHeapWord = HeapWordSize/heapOopSize;
assert(OopsPerHeapWord >= 1 && (HeapWordSize % heapOopSize == 0),
"Else the following (new) computation would be in error");
uint res = ((uint)length + OopsPerHeapWord - 1)/OopsPerHeapWord;
#ifdef ASSERT
// The old code is left in for sanity-checking; it'll
// go away pretty soon. XXX
// Without UseCompressedOops, this is simply:
// oop->length() * HeapWordsPerOop;
// With narrowOops, HeapWordsPerOop is 1/2 or equal 0 as an integer.
// The oop elements are aligned up to wordSize
const uint HeapWordsPerOop = heapOopSize/HeapWordSize;
uint old_res;
if (HeapWordsPerOop > 0) {
old_res = length * HeapWordsPerOop;
} else {
old_res = align_up((uint)length, OopsPerHeapWord)/OopsPerHeapWord;
}
assert(res == old_res, "Inconsistency between old and new.");
#endif // ASSERT
return res;
}
Thread 2 "java" hit Breakpoint 5, jni_invoke_static (env=0x7fca48029310, result=0x7fca4c534bf0, receiver=0x0, call_type=JNI_STATIC, method_id=0x7fca48542d50, args=0x7fca4c534c60, __the_thread__=0x7fca48029030) at /var/jdk/src/hotspot/share/prims/jni.cpp:881
881 args->push_arguments_on(&java_args);
(gdb) p method._value->print()
{method}
- this oop: 0x00007fca14411240
- method holder: 'com/Hello'
- constants: 0x00007fca14411020 constant pool [20] {0x00007fca14411020} for 'com/Hello' cache=0x00007fca14411348
- access: 0x9 public static
- name: 'main'
- signature: '([Ljava/lang/String;)V'
- max stack: 2
- max locals: 1
- size of params: 1
- method size: 13
- vtable index: -2
- i2i entry: 0x00007fca3900dc00
- adapters: AHE@0x00007fca4812b8d0: 0xb i2c: 0x00007fca39114d60 c2i: 0x00007fca39114e1a c2iUV: 0x00007fca39114de4 c2iNCI: 0x00007fca39114e57
- compiled entry 0x00007fca39114e1a
- code size: 10
- code start: 0x00007fca14411230
- code end (excl): 0x00007fca1441123a
- checked ex length: 0
- linenumber start: 0x00007fca1441123a
- localvar length: 0
$17 = void
(gdb) bt
#0 jni_invoke_static (env=0x7fca48029310, result=0x7fca4c534bf0, receiver=0x0, call_type=JNI_STATIC, method_id=0x7fca48542d50, args=0x7fca4c534c60, __the_thread__=0x7fca48029030) at /var/jdk/src/hotspot/share/prims/jni.cpp:881
#1 0x00007fca4d2c141c in jni_CallStaticVoidMethod (env=0x7fca48029310, cls=0x7fca4802b368, methodID=0x7fca48542d50) at /var/jdk/src/hotspot/share/prims/jni.cpp:1710
#2 0x00007fca4ea4415e in JavaMain (_args=0x7fff1ad56b60) at /var/jdk/src/java.base/share/native/libjli/java.c:545
#3 0x00007fca4ea4a5ec in ThreadJavaMain (args=0x7fff1ad56b60) at /var/jdk/src/java.base/unix/native/libjli/java_md.c:651
#4 0x00007fca4e8a5b43 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
#5 0x00007fca4e936bb4 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:100
Thread 2 "java" hit Breakpoint 5, jni_invoke_static (env=0x7f8674029310, result=0x7f86791b0bf0, receiver=0x0, call_type=JNI_STATIC, method_id=0x7f8674652560, args=0x7f86791b0c60, __the_thread__=0x7f8674029030) at /var/jdk/src/hotspot/share/prims/jni.cpp:881
881 args->push_arguments_on(&java_args);
(gdb) p method._value->print()
{method}
- this oop: 0x00007f8644411240
- method holder: 'com/Hello'
- constants: 0x00007f8644411020 constant pool [20] {0x00007f8644411020} for 'com/Hello' cache=0x00007f8644411348
- access: 0x9 public static
- name: 'main'
- signature: '([Ljava/lang/String;)V'
- max stack: 2
- max locals: 1
- size of params: 1
- method size: 13
- vtable index: -2
- i2i entry: 0x00007f866500dc00
- adapters: AHE@0x00007f867412b8d0: 0xb i2c: 0x00007f8665114d60 c2i: 0x00007f8665114e1a c2iUV: 0x00007f8665114de4 c2iNCI: 0x00007f8665114e57
- compiled entry 0x00007f8665114e1a
- code size: 10
- code start: 0x00007f8644411230
- code end (excl): 0x00007f864441123a
- checked ex length: 0
- linenumber start: 0x00007f864441123a
- localvar length: 0
$23 = void
(gdb) enable 1
(gdb) c
Continuing.
Thread 2 "java" hit Breakpoint 1, oopFactory::new_objArray (klass=0x800040f80, length=2019, __the_thread__=0x7f8674029030) at /var/jdk/src/hotspot/share/memory/oopFactory.cpp:118
118 assert(klass->is_klass(), "must be instance class");
(gdb) bt
#0 oopFactory::new_objArray (klass=0x800040f80, length=2019, __the_thread__=0x7f8674029030) at /var/jdk/src/hotspot/share/memory/oopFactory.cpp:118
#1 0x00007f8679e68a5b in InterpreterRuntime::anewarray (current=0x7f8674029030, pool=0x7f8644411020, index=2, size=2019) at /var/jdk/src/hotspot/share/interpreter/interpreterRuntime.cpp:254
#2 0x00007f8665024083 in ?? ()
#3 0x00007f867b4520a0 in TemplateInterpreter::_active_table () from /var/jdk/build/linux-x86_64-server-slowdebug/jdk/lib/server/libjvm.so
#4 0x00007f8665024002 in ?? ()
#5 0x00007f86791b07b0 in ?? ()
#6 0x00007f8644411233 in ?? ()
#7 0x00007f86791b0808 in ?? ()
#8 0x00007f8644411348 in ?? ()
#9 0x0000000000000000 in ?? ()
Bottom (innermost) frame selected; you cannot go down.
(gdb) p _do_zero
$35 = true
(gdb) n
413 if (_do_zero) {
(gdb) n
414 mem_clear(mem);
(gdb) n
416 arrayOopDesc::set_length(mem, _length);
(gdb) l
411 // concurrent GC.
412 assert(_length >= 0, "length should be non-negative");
413 if (_do_zero) {
414 mem_clear(mem);
415 }
416 arrayOopDesc::set_length(mem, _length);
417 return finish(mem);
418 }
419
420 oop ClassAllocator::initialize(HeapWord* mem) const {
(gdb) up
#1 0x00007f867a27af4b in MemAllocator::allocate (this=0x7f86791b0650) at /var/jdk/src/hotspot/share/gc/shared/memAllocator.cpp:365
365 obj = initialize(mem);
(gdb) down
#0 ObjArrayAllocator::initialize (this=0x7f86791b0650, mem=0x715e73dd0) at /var/jdk/src/hotspot/share/gc/shared/memAllocator.cpp:416
416 arrayOopDesc::set_length(mem, _length);
(gdb) s
arrayOopDesc::set_length (mem=0x715e73dd0, length=2019) at /var/jdk/src/hotspot/share/oops/arrayOop.hpp:122
122 *length_addr_impl(mem) = length;
(gdb) s
arrayOopDesc::length_addr_impl (obj_ptr=0x715e73dd0) at /var/jdk/src/hotspot/share/oops/arrayOop.hpp:66
66 char* ptr = static_cast<char*>(obj_ptr);
(gdb) l
61 return (int)hs;
62 }
63
64 // Returns the address of the length "field". See length_offset_in_bytes().
65 static int* length_addr_impl(void* obj_ptr) {
66 char* ptr = static_cast<char*>(obj_ptr);
67 return reinterpret_cast<int*>(ptr + length_offset_in_bytes());
68 }
69
70 // Check whether an element of a typeArrayOop with the given type must be
(gdb) n
67 return reinterpret_cast<int*>(ptr + length_offset_in_bytes());
(gdb) s
arrayOopDesc::length_offset_in_bytes () at /var/jdk/src/hotspot/share/oops/arrayOop.hpp:83
83 sizeof(arrayOopDesc);
(gdb) l
78 // The _length field is not declared in C++. It is allocated after the
79 // declared nonstatic fields in arrayOopDesc if not compressed, otherwise
80 // it occupies the second half of the _klass field in oopDesc.
81 static int length_offset_in_bytes() {
82 return UseCompressedClassPointers ? klass_gap_offset_in_bytes() :
83 sizeof(arrayOopDesc);
84 }
85
86 // Returns the offset of the first element.
87 static int base_offset_in_bytes(BasicType type) {
(gdb) p Use
Display all 161 possibilities? (y or n)
(gdb) p UseCompressedClassPointers
$36 = true
(gdb) s
82 return UseCompressedClassPointers ? klass_gap_offset_in_bytes() :
(gdb) s
oopDesc::klass_gap_offset_in_bytes () at /var/jdk/src/hotspot/share/oops/oop.hpp:307
307 assert(has_klass_gap(), "only applicable to compressed klass pointers");
(gdb) l
302
303 // for code generation
304 static int mark_offset_in_bytes() { return offset_of(oopDesc, _mark); }
305 static int klass_offset_in_bytes() { return offset_of(oopDesc, _metadata._klass); }
306 static int klass_gap_offset_in_bytes() {
307 assert(has_klass_gap(), "only applicable to compressed klass pointers");
308 return klass_offset_in_bytes() + sizeof(narrowKlass);
309 }
310
311 // for error reporting
(gdb) n
oopDesc::klass_gap_offset_in_bytes () at /var/jdk/src/hotspot/share/oops/oop.hpp:308
308 return klass_offset_in_bytes() + sizeof(narrowKlass);
(gdb) n
309 }
(gdb) n
arrayOopDesc::length_offset_in_bytes () at /var/jdk/src/hotspot/share/oops/arrayOop.hpp:83
83 sizeof(arrayOopDesc);
(gdb) n
84 }
(gdb) n
arrayOopDesc::length_addr_impl (obj_ptr=0x715e73dd0) at /var/jdk/src/hotspot/share/oops/arrayOop.hpp:68
68 }
(gdb) n
arrayOopDesc::set_length (mem=0x715e73dd0, length=2019) at /var/jdk/src/hotspot/share/oops/arrayOop.hpp:122
122 *length_addr_impl(mem) = length;
(gdb) n
123 }
(gdb) p (int *)mem@20
Only values in memory can be extended with '@'.
(gdb) p *(int *)mem@20
$37 = {-1163019586, -1163019586, -1163019586, 2019, 0 <repeats 16 times>}
// jdk/src/hotspot/share/interpreter/templateInterpreter.cpp
void DispatchTable::set_entry(int i, EntryPoint& entry) {
assert(0 <= i && i < length, "index out of bounds");
assert(number_of_states == 10, "check the code below");
_table[btos][i] = entry.entry(btos);
_table[ztos][i] = entry.entry(ztos);
_table[ctos][i] = entry.entry(ctos);
_table[stos][i] = entry.entry(stos);
_table[atos][i] = entry.entry(atos);
_table[itos][i] = entry.entry(itos);
_table[ltos][i] = entry.entry(ltos);
_table[ftos][i] = entry.entry(ftos);
_table[dtos][i] = entry.entry(dtos);
_table[vtos][i] = entry.entry(vtos);
}
//src/hotspot/share/interpreter/bytecodes.hpp
_new = 187, // 0xbb
_newarray = 188, // 0xbc
_anewarray = 189, // 0xbd
_arraylength = 190, // 0xbe
堆栈:
Thread 2 "java" hit Breakpoint 13, 0x00007fffe1011b13 in ?? ()
(gdb) x/20i $pc
=> 0x7fffe1011b13: movzwl 0x1(%r13),%eax
0x7fffe1011b18: bswap %eax
0x7fffe1011b1a: sar $0x10,%eax
0x7fffe1011b1d: movzbl 0x3(%r13),%ebx
0x7fffe1011b22: add $0x3,%r13
0x7fffe1011b26: movabs $0x7ffff7bca0a0,%r10
0x7fffe1011b30: jmp *(%r10,%rbx,8)
0x7fffe1011b34: nop
0x7fffe1011b35: nop
0x7fffe1011b36: nop
0x7fffe1011b37: nop
0x7fffe1011b38: int3
0x7fffe1011b39: int3
0x7fffe1011b3a: int3
0x7fffe1011b3b: int3
0x7fffe1011b3c: int3
0x7fffe1011b3d: int3
0x7fffe1011b3e: int3
0x7fffe1011b3f: int3
0x7fffe1011b40: and %al,(%rax,%rax,1)
0x00007fffe1011b1d in ?? ()
(gdb) info registers
rax 0x2805 10245
rbx 0x11 17
rcx 0x2 2
rdx 0x8 8
rsi 0x555555581230 93824992416304
rdi 0x7ffff0028f70 140737220087664
rbp 0x7ffff59fe7f8 0x7ffff59fe7f8
rsp 0x7ffff59fe7b0 0x7ffff59fe7b0
r8 0x8 8
r9 0x0 0
r10 0x7ffff7bcc8a0 140737349732512
r11 0x216 534
r12 0x0 0
r13 0x7fffb4411230 140736217551408
r14 0x7ffff59fe808 140737314285576
r15 0x7ffff0028f70 140737220087664
rip 0x7fffe1011b1d 0x7fffe1011b1d
eflags 0x216 [ PF AF IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
anewarray 汇编代码:
(gdb) x/20i $pc
=> 0x7fffe102400a: lea 0x8(%rsp),%rax
0x7fffe102400f: mov %r13,-0x40(%rbp)
0x7fffe1024013: cmpq $0x0,-0x10(%rbp)
0x7fffe102401b: je 0x7fffe1024035
0x7fffe1024021: movabs $0x7ffff71becc8,%rdi
0x7fffe102402b: and $0xfffffffffffffff0,%rsp
0x7fffe102402f: call 0x7ffff694f3c0 <_ZN14MacroAssembler7debug64EPclPl>
0x7fffe1024034: hlt
0x7fffe1024035: push %r10
0x7fffe1024037: cmp 0x16ae2ec2(%rip),%r12 # 0x7ffff7b06f00 <_ZN14CompressedOops11_narrow_oopE>
0x7fffe102403e: je 0x7fffe1024058
0x7fffe1024044: movabs $0x7ffff7311c28,%rdi
0x7fffe102404e: and $0xfffffffffffffff0,%rsp
0x7fffe1024052: call 0x7ffff694f3c0 <_ZN14MacroAssembler7debug64EPclPl>
0x7fffe1024057: hlt
0x7fffe1024058: pop %r10
0x7fffe102405a: mov %r15,%rdi
0x7fffe102405d: vzeroupper
0x7fffe1024060: mov %rbp,0x2d0(%r15)
0x7fffe1024067: mov %rax,0x2c0(%r15)
(gdb) x/200i $pc
=> 0x7fffe102400a: lea 0x8(%rsp),%rax
0x7fffe102400f: mov %r13,-0x40(%rbp)
0x7fffe1024013: cmpq $0x0,-0x10(%rbp)
0x7fffe102401b: je 0x7fffe1024035
0x7fffe1024021: movabs $0x7ffff71becc8,%rdi
0x7fffe102402b: and $0xfffffffffffffff0,%rsp
0x7fffe102402f: call 0x7ffff694f3c0 <_ZN14MacroAssembler7debug64EPclPl>
0x7fffe1024034: hlt
0x7fffe1024035: push %r10
0x7fffe1024037: cmp 0x16ae2ec2(%rip),%r12 # 0x7ffff7b06f00 <_ZN14CompressedOops11_narrow_oopE>
0x7fffe102403e: je 0x7fffe1024058
0x7fffe1024044: movabs $0x7ffff7311c28,%rdi
0x7fffe102404e: and $0xfffffffffffffff0,%rsp
0x7fffe1024052: call 0x7ffff694f3c0 <_ZN14MacroAssembler7debug64EPclPl>
0x7fffe1024057: hlt
0x7fffe1024058: pop %r10
0x7fffe102405a: mov %r15,%rdi
0x7fffe102405d: vzeroupper
0x7fffe1024060: mov %rbp,0x2d0(%r15)
0x7fffe1024067: mov %rax,0x2c0(%r15)
0x7fffe102406e: test $0xf,%esp
0x7fffe1024074: je 0x7fffe102408c
0x7fffe102407a: sub $0x8,%rsp
0x7fffe102407e: call 0x7ffff65cf968 <_ZN18InterpreterRuntime9anewarrayEP10JavaThreadP12ConstantPoolii>
0x7fffe1024083: add $0x8,%rsp
0x7fffe1024087: jmp 0x7fffe1024091
0x7fffe102408c: call 0x7ffff65cf968 <_ZN18InterpreterRuntime9anewarrayEP10JavaThreadP12ConstantPoolii>
0x7fffe1024091: push %rax
0x7fffe1024092: push %rdi
0x7fffe1024093: push %rsi
0x7fffe1024094: push %rdx
--Type <RET> for more, q to quit, c to continue without paging--
0x7fffe1024095: push %rcx
0x7fffe1024096: push %r8
0x7fffe1024098: push %r9
0x7fffe102409a: push %r10
0x7fffe102409c: push %r11
0x7fffe102409e: test $0xf,%esp
0x7fffe10240a4: je 0x7fffe10240bc
0x7fffe10240aa: sub $0x8,%rsp
0x7fffe10240ae: call 0x7ffff5d1c04e <_ZN6Thread7currentEv>
0x7fffe10240b3: add $0x8,%rsp
0x7fffe10240b7: jmp 0x7fffe10240c1
0x7fffe10240bc: call 0x7ffff5d1c04e <_ZN6Thread7currentEv>
0x7fffe10240c1: pop %r11
0x7fffe10240c3: pop %r10
0x7fffe10240c5: pop %r9
0x7fffe10240c7: pop %r8
0x7fffe10240c9: pop %rcx
0x7fffe10240ca: pop %rdx
0x7fffe10240cb: pop %rsi
0x7fffe10240cc: pop %rdi
0x7fffe10240cd: cmp %rax,%r15
0x7fffe10240d0: je 0x7fffe10240ea
0x7fffe10240d6: movabs $0x7ffff7311da0,%rdi
0x7fffe10240e0: and $0xfffffffffffffff0,%rsp
0x7fffe10240e4: call 0x7ffff694f3c0 <_ZN14MacroAssembler7debug64EPclPl>
0x7fffe10240e9: hlt
0x7fffe10240ea: pop %rax
0x7fffe10240eb: movq $0x0,0x2c0(%r15)
0x7fffe10240f6: movq $0x0,0x2d0(%r15)
0x7fffe1024101: movq $0x0,0x2c8(%r15)
0x7fffe102410c: vzeroupper
--Type <RET> for more, q to quit, c to continue without paging--
0x7fffe102410f: cmpq $0x0,0x8(%r15)
0x7fffe1024117: je 0x7fffe1024122
0x7fffe102411d: jmp 0x7fffe1000c20
0x7fffe1024122: mov 0x318(%r15),%rax
0x7fffe1024129: movq $0x0,0x318(%r15)
0x7fffe1024134: mov -0x40(%rbp),%r13
0x7fffe1024138: mov -0x38(%rbp),%r14
0x7fffe102413c: ret
0x7fffe102413d: movzbl 0x3(%r13),%ebx
0x7fffe1024142: add $0x3,%r13
0x7fffe1024146: movabs $0x7ffff7bcc0a0,%r10
0x7fffe1024150: jmp *(%r10,%rbx,8)
0x7fffe1024154: nop
0x7fffe1024155: nop
用的是jdk11以上版本,我这个jdk是用g1来做gc的,所以看看g1 是怎么分配的
(gdb) bt
#0 HeapRegion::par_allocate_impl (this=0x7ffff00e11b0, min_word_size=256, desired_word_size=63020, actual_size=0x7ffff59fcba8)
at /home/dai/jdk/src/hotspot/share/gc/g1/heapRegion.inline.hpp:63
#1 0x00007ffff640bdcc in HeapRegion::par_allocate (this=0x7ffff00e11b0, min_word_size=256, desired_word_size=63020, actual_word_size=0x7ffff59fcba8)
at /home/dai/jdk/src/hotspot/share/gc/g1/heapRegion.inline.hpp:225
#2 0x00007ffff640bfcb in G1AllocRegion::par_allocate (this=0x7ffff0052e10, alloc_region=0x7ffff00e11b0, min_word_size=256, desired_word_size=63020,
actual_word_size=0x7ffff59fcba8) at /home/dai/jdk/src/hotspot/share/gc/g1/g1AllocRegion.inline.hpp:63
#3 0x00007ffff640c0c6 in G1AllocRegion::attempt_allocation (this=0x7ffff0052e10, min_word_size=256, desired_word_size=63020, actual_word_size=0x7ffff59fcba8)
at /home/dai/jdk/src/hotspot/share/gc/g1/g1AllocRegion.inline.hpp:77
#4 0x00007ffff6447142 in G1Allocator::attempt_allocation (this=0x7ffff0052d50, min_word_size=256, desired_word_size=63020, actual_word_size=0x7ffff59fcba8)
at /home/dai/jdk/src/hotspot/share/gc/g1/g1Allocator.inline.hpp:62
#5 0x00007ffff6447b1d in G1CollectedHeap::attempt_allocation (this=0x7ffff0048bf0, min_word_size=256, desired_word_size=63020,
actual_word_size=0x7ffff59fcba8) at /home/dai/jdk/src/hotspot/share/gc/g1/g1CollectedHeap.cpp:709
#6 0x00007ffff64385ea in G1CollectedHeap::allocate_new_tlab (this=0x7ffff0048bf0, min_size=256, requested_size=63020, actual_size=0x7ffff59fcba8)
at /home/dai/jdk/src/hotspot/share/gc/g1/g1CollectedHeap.cpp:359
#7 0x00007ffff69e1cf6 in MemAllocator::allocate_inside_tlab_slow (this=0x7ffff59fcc00, allocation=...)
at /home/dai/jdk/src/hotspot/share/gc/shared/memAllocator.cpp:318
#8 0x00007ffff69e1bc2 in MemAllocator::allocate_inside_tlab (this=0x7ffff59fcc00, allocation=...)
at /home/dai/jdk/src/hotspot/share/gc/shared/memAllocator.cpp:278
#9 0x00007ffff69e1eb9 in MemAllocator::mem_allocate (this=0x7ffff59fcc00, allocation=...) at /home/dai/jdk/src/hotspot/share/gc/shared/memAllocator.cpp:350
#10 0x00007ffff69e1f22 in MemAllocator::allocate (this=0x7ffff59fcc00) at /home/dai/jdk/src/hotspot/share/gc/shared/memAllocator.cpp:363
#11 0x00007ffff6260d84 in CollectedHeap::array_allocate (this=0x7ffff0048bf0, klass=0x8000407c0, size=106, length=825, do_zero=true,
__the_thread__=0x7ffff0028f70) at /home/dai/jdk/src/hotspot/share/gc/shared/collectedHeap.inline.hpp:41
#12 0x00007ffff6db9bf2 in TypeArrayKlass::allocate_common (this=0x8000407c0, length=825, do_zero=true, __the_thread__=0x7ffff0028f70)
at /home/dai/jdk/src/hotspot/share/oops/typeArrayKlass.cpp:93
#13 0x00007ffff62f7428 in TypeArrayKlass::allocate (this=0x8000407c0, length=825, __the_thread__=0x7ffff0028f70)
at /home/dai/jdk/src/hotspot/share/oops/typeArrayKlass.hpp:68
#14 0x00007ffff6ab4757 in oopFactory::new_typeArray (type=T_BYTE, length=825, __the_thread__=0x7ffff0028f70)
at /home/dai/jdk/src/hotspot/share/memory/oopFactory.cpp:93
#15 0x00007ffff65cf8e5 in InterpreterRuntime::newarray (current=0x7ffff0028f70, type=T_BYTE, size=825)
at /home/dai/jdk/src/hotspot/share/interpreter/interpreterRuntime.cpp:247
#16 0x00007fffe1023eb2 in ?? ()
#17 0x00007ffff7bca0a0 in TemplateInterpreter::_active_table () from /home/dai/jdk/build/linux-x86_64-server-slowdebug/jdk/lib/server/libjvm.so
#18 0x00007fffe1023e31 in ?? ()
#19 0x000000062a47ab38 in ?? ()
#20 0x00007ffff59fcd88 in ?? ()
#21 0x00007fffb43a23e6 in ?? ()
#22 0x00007ffff59fcde8 in ?? ()
#23 0x00007fffb43a3520 in ?? ()
#24 0x0000000000000000 in ?? ()
java里面 System.arraycopy 函数就是copy 整个数组到新的数组里面,复制方式是浅拷贝.
最后调用的入口是下面的c++代码.所以可以通过这个函数就可以了解数组的内存布局
void ObjArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d,
int dst_pos, int length, TRAPS) {
...
size_t src_offset = (size_t) objArrayOopDesc::obj_at_offset<oop>(src_pos); <----------------------------- 开始地址
size_t dst_offset = (size_t) objArrayOopDesc::obj_at_offset<oop>(dst_pos); <---------------------------- 结束地址
assert(arrayOopDesc::obj_offset_to_raw<oop>(s, src_offset, NULL) ==
objArrayOop(s)->obj_at_addr<oop>(src_pos), "sanity");
assert(arrayOopDesc::obj_offset_to_raw<oop>(d, dst_offset, NULL) ==
objArrayOop(d)->obj_at_addr<oop>(dst_pos), "sanity");
do_copy(s, src_offset, d, dst_offset, length, CHECK);
}
}
所以java的对象数组的内存布局就像下面一样 , 这里的oop 是一个指针
64位下面是8字节
java的redis操作使用redission封装
一个简单的堆栈堆栈
比较核心的堆栈
encode:132, CommandEncoder (org.redisson.client.handler)
encode:99, CommandEncoder (org.redisson.client.handler)
encode:55, CommandEncoder (org.redisson.client.handler)
write:107, MessageToByteEncoder (io.netty.handler.codec)
write:75, CommandEncoder (org.redisson.client.handler)
invokeWrite0:881, AbstractChannelHandlerContext (io.netty.channel)
invokeWrite:863, AbstractChannelHandlerContext (io.netty.channel)
write:968, AbstractChannelHandlerContext (io.netty.channel)
write:856, AbstractChannelHandlerContext (io.netty.channel)
write:120, MessageToByteEncoder (io.netty.handler.codec)
write:45, CommandBatchEncoder (org.redisson.client.handler)
invokeWrite0:881, AbstractChannelHandlerContext (io.netty.channel)
invokeWriteAndFlush:940, AbstractChannelHandlerContext (io.netty.channel)
write:966, AbstractChannelHandlerContext (io.netty.channel)
writeAndFlush:934, AbstractChannelHandlerContext (io.netty.channel)
write:83, CommandsQueue (org.redisson.client.handler)
invokeWrite0:879, AbstractChannelHandlerContext (io.netty.channel)
invokeWriteAndFlush:940, AbstractChannelHandlerContext (io.netty.channel)
run:1247, AbstractChannelHandlerContext$WriteTask (io.netty.channel)
runTask$$$capture:174, AbstractEventExecutor (io.netty.util.concurrent)
runTask:-1, AbstractEventExecutor (io.netty.util.concurrent)
- Async stack trace
addTask:-1, SingleThreadEventExecutor (io.netty.util.concurrent)
execute:836, SingleThreadEventExecutor (io.netty.util.concurrent)
execute0:827, SingleThreadEventExecutor (io.netty.util.concurrent)
execute:817, SingleThreadEventExecutor (io.netty.util.concurrent)
safeExecute:1165, AbstractChannelHandlerContext (io.netty.channel)
write:972, AbstractChannelHandlerContext (io.netty.channel)
writeAndFlush:934, AbstractChannelHandlerContext (io.netty.channel)
writeAndFlush:984, AbstractChannelHandlerContext (io.netty.channel)
writeAndFlush:1025, DefaultChannelPipeline (io.netty.channel)
writeAndFlush:306, AbstractChannel (io.netty.channel)
send:206, RedisConnection (org.redisson.client)
sendCommand:590, RedisExecutor (org.redisson.command)
lambda$execute$3:164, RedisExecutor (org.redisson.command)
uniWhenComplete:859, CompletableFuture (java.util.concurrent)
uniWhenCompleteStage:883, CompletableFuture (java.util.concurrent)
whenComplete:2251, CompletableFuture (java.util.concurrent)
execute:149, RedisExecutor (org.redisson.command)
async:526, CommandAsyncService (org.redisson.command)
writeAsync:490, CommandAsyncService (org.redisson.command)
setAsync:192, RedissonBucket (org.redisson)
set:183, RedissonBucket (org.redisson)
main:25, App (com.demo.redission)
allocateMemory:608, Unsafe (jdk.internal.misc)
<init>:122, DirectByteBuffer (java.nio)
allocateDirect:317, ByteBuffer (java.nio)
<clinit>:93, PlatformDependent0 (io.netty.util.internal)
isAndroid:333, PlatformDependent (io.netty.util.internal)
<clinit>:88, PlatformDependent (io.netty.util.internal)
<clinit>:84, NioEventLoop (io.netty.channel.nio)
newChild:182, NioEventLoopGroup (io.netty.channel.nio)
newChild:38, NioEventLoopGroup (io.netty.channel.nio)
<init>:84, MultithreadEventExecutorGroup (io.netty.util.concurrent)
<init>:60, MultithreadEventExecutorGroup (io.netty.util.concurrent)
<init>:49, MultithreadEventExecutorGroup (io.netty.util.concurrent)
<init>:59, MultithreadEventLoopGroup (io.netty.channel)
<init>:87, NioEventLoopGroup (io.netty.channel.nio)
<init>:82, NioEventLoopGroup (io.netty.channel.nio)
<init>:69, NioEventLoopGroup (io.netty.channel.nio)
<init>:181, MasterSlaveConnectionManager (org.redisson.connection)
<init>:73, ClusterConnectionManager (org.redisson.cluster)
createConnectionManager:196, ConfigSupport (org.redisson.config)
<init>:68, Redisson (org.redisson)
create:109, Redisson (org.redisson)
main:24, App (com.demo.redission)
putByte:704, PlatformDependent0 (io.netty.util.internal)
putByte:719, PlatformDependent (io.netty.util.internal)
unsafeWriteUtf8:1020, ByteBufUtil (io.netty.buffer)
writeUtf8:836, ByteBufUtil (io.netty.buffer)
writeUtf8:820, ByteBufUtil (io.netty.buffer)
setCharSequence0:707, AbstractByteBuf (io.netty.buffer)
writeCharSequence:1187, AbstractByteBuf (io.netty.buffer)
encode:45, StringCodec$1 (org.redisson.client.codec)
encode:622, CommandAsyncService (org.redisson.command)
encode:313, RedissonObject (org.redisson)
setAsync:192, RedissonBucket (org.redisson)
set:183, RedissonBucket (org.redisson)
testApp:57, AppTest (com.demo.redission)
invokeVirtual:-1, LambdaForm$DMH/0x0000000800c0c400 (java.lang.invoke)
invoke:-1, LambdaForm$MH/0x0000000800c0d000 (java.lang.invoke)
invokeExact_MT:-1, Invokers$Holder (java.lang.invoke)
invokeImpl:154, DirectMethodHandleAccessor (jdk.internal.reflect)
invoke:104, DirectMethodHandleAccessor (jdk.internal.reflect)
invoke:577, Method (java.lang.reflect)
runTest:154, TestCase (junit.framework)
runBare:127, TestCase (junit.framework)
protect:106, TestResult$1 (junit.framework)
runProtected:124, TestResult (junit.framework)
run:109, TestResult (junit.framework)
run:118, TestCase (junit.framework)
doRun:116, TestRunner (junit.textui)
doRun:117, JUnit3IdeaTestRunner (com.intellij.junit3)
doRun:109, TestRunner (junit.textui)
startRunnerWithArgs:38, JUnit3IdeaTestRunner (com.intellij.junit3)
execute:38, IdeaTestRunner$Repeater$1 (com.intellij.rt.junit)
repeat:11, TestsRepeater (com.intellij.rt.execution.junit)
startRunnerWithArgs:35, IdeaTestRunner$Repeater (com.intellij.rt.junit)
prepareStreamsAndStart:235, JUnitStarter (com.intellij.rt.junit)
main:54, JUnitStarter (com.intellij.rt.junit)
ByteBuf 最后会调用UNSAFE.putByte(data, offset, value); 写入
write:62, SocketDispatcher (sun.nio.ch)
writeFromNativeBuffer:137, IOUtil (sun.nio.ch)
write:81, IOUtil (sun.nio.ch)
write:58, IOUtil (sun.nio.ch)
write:532, SocketChannelImpl (sun.nio.ch)
doWrite:415, NioSocketChannel (io.netty.channel.socket.nio)
flush0:931, AbstractChannel$AbstractUnsafe (io.netty.channel)
flush0:354, AbstractNioChannel$AbstractNioUnsafe (io.netty.channel.nio)
flush:895, AbstractChannel$AbstractUnsafe (io.netty.channel)
flush:1372, DefaultChannelPipeline$HeadContext (io.netty.channel)
invokeFlush0:921, AbstractChannelHandlerContext (io.netty.channel)
invokeFlush:907, AbstractChannelHandlerContext (io.netty.channel)
flush:893, AbstractChannelHandlerContext (io.netty.channel)
flush:125, ChannelOutboundHandlerAdapter (io.netty.channel)
invokeFlush0:925, AbstractChannelHandlerContext (io.netty.channel)
invokeWriteAndFlush:941, AbstractChannelHandlerContext (io.netty.channel)
write:966, AbstractChannelHandlerContext (io.netty.channel)
writeAndFlush:934, AbstractChannelHandlerContext (io.netty.channel)
write:83, CommandsQueue (org.redisson.client.handler)
invokeWrite0:879, AbstractChannelHandlerContext (io.netty.channel)
invokeWriteAndFlush:940, AbstractChannelHandlerContext (io.netty.channel)
run:1247, AbstractChannelHandlerContext$WriteTask (io.netty.channel)
runTask$$$capture:174, AbstractEventExecutor (io.netty.util.concurrent)
runTask:-1, AbstractEventExecutor (io.netty.util.concurrent)
- Async stack trace
addTask:-1, SingleThreadEventExecutor (io.netty.util.concurrent)
execute:836, SingleThreadEventExecutor (io.netty.util.concurrent)
execute0:827, SingleThreadEventExecutor (io.netty.util.concurrent)
execute:817, SingleThreadEventExecutor (io.netty.util.concurrent)
safeExecute:1165, AbstractChannelHandlerContext (io.netty.channel)
write:972, AbstractChannelHandlerContext (io.netty.channel)
writeAndFlush:934, AbstractChannelHandlerContext (io.netty.channel)
writeAndFlush:984, AbstractChannelHandlerContext (io.netty.channel)
writeAndFlush:1025, DefaultChannelPipeline (io.netty.channel)
writeAndFlush:306, AbstractChannel (io.netty.channel)
send:206, RedisConnection (org.redisson.client)
sendCommand:590, RedisExecutor (org.redisson.command)
lambda$execute$3:164, RedisExecutor (org.redisson.command)
uniWhenComplete:863, CompletableFuture (java.util.concurrent)
uniWhenCompleteStage:887, CompletableFuture (java.util.concurrent)
whenComplete:2325, CompletableFuture (java.util.concurrent)
execute:149, RedisExecutor (org.redisson.command)
async:526, CommandAsyncService (org.redisson.command)
readAsync:292, CommandAsyncService (org.redisson.command)
getAsync:140, RedissonBucket (org.redisson)
get:135, RedissonBucket (org.redisson)
testApp:59, AppTest (com.demo.redission)
invoke:104, DirectMethodHandleAccessor (jdk.internal.reflect)
invoke:577, Method (java.lang.reflect)
runTest:154, TestCase (junit.framework)
runBare:127, TestCase (junit.framework)
protect:106, TestResult$1 (junit.framework)
runProtected:124, TestResult (junit.framework)
run:109, TestResult (junit.framework)
run:118, TestCase (junit.framework)
doRun:116, TestRunner (junit.textui)
doRun:117, JUnit3IdeaTestRunner (com.intellij.junit3)
doRun:109, TestRunner (junit.textui)
startRunnerWithArgs:38, JUnit3IdeaTestRunner (com.intellij.junit3)
execute:38, IdeaTestRunner$Repeater$1 (com.intellij.rt.junit)
repeat:11, TestsRepeater (com.intellij.rt.execution.junit)
startRunnerWithArgs:35, IdeaTestRunner$Repeater (com.intellij.rt.junit)
prepareStreamsAndStart:235, JUnitStarter (com.intellij.rt.junit)
main:54, JUnitStarter (com.intellij.rt.junit)
public ByteBuffer[] nioBuffers(int maxCount, long maxBytes) {
...
ByteBuffer[] nioBuffers = NIO_BUFFERS.get(threadLocalMap);
Entry entry = flushedEntry;
while (isFlushedEntry(entry) && entry.msg instanceof ByteBuf) {
if (!entry.cancelled) {
ByteBuf buf = (ByteBuf) entry.msg;
final int readerIndex = buf.readerIndex();
final int readableBytes = buf.writerIndex() - readerIndex;
if (readableBytes > 0) {
nioBufferSize += readableBytes;
int count = entry.count;
if (count == -1) {
//noinspection ConstantValueVariableUse
entry.count = count = buf.nioBufferCount();
}
int neededSpace = min(maxCount, nioBufferCount + count);
if (neededSpace > nioBuffers.length) {
nioBuffers = expandNioBufferArray(nioBuffers, neededSpace, nioBufferCount);
NIO_BUFFERS.set(threadLocalMap, nioBuffers);
}
if (count == 1) {
ByteBuffer nioBuf = entry.buf;
if (nioBuf == null) {
// cache ByteBuffer as it may need to create a new ByteBuffer instance if its a
// derived buffer
entry.buf = nioBuf = buf.internalNioBuffer(readerIndex, readableBytes); // 转换
}
nioBuffers[nioBufferCount++] = nioBuf;
} else {
// The code exists in an extra method to ensure the method is not too big to inline as this
// branch is not very likely to get hit very frequently.
nioBufferCount = nioBuffers(entry, buf, nioBuffers, nioBufferCount, maxCount); // 转换nioBuffers
}
if (nioBufferCount >= maxCount) {
break;
}
}
}
entry = entry.next;
}
this.nioBufferCount = nioBufferCount;
this.nioBufferSize = nioBufferSize;
return nioBuffers;
}
写入ByteBuf 转换到ByteBuffer 的过程, 最后调用的是PooledByteBuf.internalNioBuffer 这个方法
internalNioBuffer:158, PooledByteBuf (io.netty.buffer)
_internalNioBuffer:194, PooledByteBuf (io.netty.buffer)
internalNioBuffer:207, PooledByteBuf (io.netty.buffer)
nioBuffers:447, ChannelOutboundBuffer (io.netty.channel)
doWrite:399, NioSocketChannel (io.netty.channel.socket.nio)
flush0:931, AbstractChannel$AbstractUnsafe (io.netty.channel)
flush0:354, AbstractNioChannel$AbstractNioUnsafe (io.netty.channel.nio)
flush:895, AbstractChannel$AbstractUnsafe (io.netty.channel)
flush:1372, DefaultChannelPipeline$HeadContext (io.netty.channel)
invokeFlush0:921, AbstractChannelHandlerContext (io.netty.channel)
invokeFlush:907, AbstractChannelHandlerContext (io.netty.channel)
flush:893, AbstractChannelHandlerContext (io.netty.channel)
flush:125, ChannelOutboundHandlerAdapter (io.netty.channel)
invokeFlush0:925, AbstractChannelHandlerContext (io.netty.channel)
invokeWriteAndFlush:941, AbstractChannelHandlerContext (io.netty.channel)
write:966, AbstractChannelHandlerContext (io.netty.channel)
writeAndFlush:934, AbstractChannelHandlerContext (io.netty.channel)
write:83, CommandsQueue (org.redisson.client.handler)
invokeWrite0:879, AbstractChannelHandlerContext (io.netty.channel)
invokeWriteAndFlush:940, AbstractChannelHandlerContext (io.netty.channel)
run:1247, AbstractChannelHandlerContext$WriteTask (io.netty.channel)
runTask$$$capture:174, AbstractEventExecutor (io.netty.util.concurrent)
runTask:-1, AbstractEventExecutor (io.netty.util.concurrent)
- Async stack trace
addTask:-1, SingleThreadEventExecutor (io.netty.util.concurrent)
execute:836, SingleThreadEventExecutor (io.netty.util.concurrent)
execute0:827, SingleThreadEventExecutor (io.netty.util.concurrent)
execute:817, SingleThreadEventExecutor (io.netty.util.concurrent)
safeExecute:1165, AbstractChannelHandlerContext (io.netty.channel)
write:972, AbstractChannelHandlerContext (io.netty.channel)
writeAndFlush:934, AbstractChannelHandlerContext (io.netty.channel)
writeAndFlush:984, AbstractChannelHandlerContext (io.netty.channel)
writeAndFlush:1025, DefaultChannelPipeline (io.netty.channel)
writeAndFlush:306, AbstractChannel (io.netty.channel)
send:206, RedisConnection (org.redisson.client)
sync:215, RedisConnection (org.redisson.client)
sync:202, RedisConnection (org.redisson.client)
<init>:100, ClusterConnectionManager (org.redisson.cluster)
createConnectionManager:196, ConfigSupport (org.redisson.config)
<init>:68, Redisson (org.redisson)
create:109, Redisson (org.redisson)
main:24, App (com.demo.redission)
创建链接的过程:
createConnection:36, RedisConnectionHandler (org.redisson.client.handler)
channelRegistered:53, BaseConnectionHandler (org.redisson.client.handler)
invokeChannelRegistered:176, AbstractChannelHandlerContext (io.netty.channel)
invokeChannelRegistered:152, AbstractChannelHandlerContext (io.netty.channel) [2]
fireChannelRegistered:145, AbstractChannelHandlerContext (io.netty.channel)
channelRegistered:1383, DefaultChannelPipeline$HeadContext (io.netty.channel)
invokeChannelRegistered:172, AbstractChannelHandlerContext (io.netty.channel)
invokeChannelRegistered:152, AbstractChannelHandlerContext (io.netty.channel) [1]
fireChannelRegistered:815, DefaultChannelPipeline (io.netty.channel)
register0:517, AbstractChannel$AbstractUnsafe (io.netty.channel)
access$200:429, AbstractChannel$AbstractUnsafe (io.netty.channel)
run:486, AbstractChannel$AbstractUnsafe$1 (io.netty.channel)
runTask$$$capture:174, AbstractEventExecutor (io.netty.util.concurrent)
runTask:-1, AbstractEventExecutor (io.netty.util.concurrent)
- Async stack trace
addTask:-1, SingleThreadEventExecutor (io.netty.util.concurrent)
execute:836, SingleThreadEventExecutor (io.netty.util.concurrent)
execute0:827, SingleThreadEventExecutor (io.netty.util.concurrent)
execute:817, SingleThreadEventExecutor (io.netty.util.concurrent)
register:483, AbstractChannel$AbstractUnsafe (io.netty.channel)
register:89, SingleThreadEventLoop (io.netty.channel)
register:83, SingleThreadEventLoop (io.netty.channel)
register:86, MultithreadEventLoopGroup (io.netty.channel)
initAndRegister:323, AbstractBootstrap (io.netty.bootstrap)
doResolveAndConnect:155, Bootstrap (io.netty.bootstrap)
connect:139, Bootstrap (io.netty.bootstrap)
lambda$connectAsync$1:220, RedisClient (org.redisson.client)
uniComposeStage:1187, CompletableFuture (java.util.concurrent)
thenCompose:2309, CompletableFuture (java.util.concurrent)
connectAsync:218, RedisClient (org.redisson.client)
connect:189, ClientConnectionsEntry (org.redisson.connection)
connect:249, ConnectionPool (org.redisson.connection.pool)
createConnection:274, ConnectionPool (org.redisson.connection.pool)
lambda$createConnection$1:112, ConnectionPool (org.redisson.connection.pool)
uniAcceptNow:757, CompletableFuture (java.util.concurrent)
uniAcceptStage:735, CompletableFuture (java.util.concurrent)
thenAccept:2182, CompletableFuture (java.util.concurrent)
createConnection:110, ConnectionPool (org.redisson.connection.pool)
initConnections:92, ConnectionPool (org.redisson.connection.pool)
add:69, ConnectionPool (org.redisson.connection.pool)
add:34, MasterConnectionPool (org.redisson.connection.pool)
lambda$setupMasterEntry$1:139, MasterSlaveEntry (org.redisson.connection)
uniComposeStage:1187, CompletableFuture (java.util.concurrent)
thenCompose:2309, CompletableFuture (java.util.concurrent)
setupMasterEntry:122, MasterSlaveEntry (org.redisson.connection)
setupMasterEntry:117, MasterSlaveEntry (org.redisson.connection)
setupMasterEntry:112, MasterSlaveEntry (org.redisson.connection)
initSingleEntry:330, MasterSlaveConnectionManager (org.redisson.connection)
<init>:146, MasterSlaveConnectionManager (org.redisson.connection)
<init>:30, SingleConnectionManager (org.redisson.connection)
createConnectionManager:190, ConfigSupport (org.redisson.config)
<init>:68, Redisson (org.redisson)
create:109, Redisson (org.redisson)
testApp:58, AppTest (com.demo.redission)
invoke:104, DirectMethodHandleAccessor (jdk.internal.reflect)
invoke:577, Method (java.lang.reflect)
runTest:154, TestCase (junit.framework)
runBare:127, TestCase (junit.framework)
protect:106, TestResult$1 (junit.framework)
runProtected:124, TestResult (junit.framework)
run:109, TestResult (junit.framework)
run:118, TestCase (junit.framework)
doRun:116, TestRunner (junit.textui)
doRun:117, JUnit3IdeaTestRunner (com.intellij.junit3)
doRun:109, TestRunner (junit.textui)
startRunnerWithArgs:38, JUnit3IdeaTestRunner (com.intellij.junit3)
execute:38, IdeaTestRunner$Repeater$1 (com.intellij.rt.junit)
repeat:11, TestsRepeater (com.intellij.rt.execution.junit)
startRunnerWithArgs:35, IdeaTestRunner$Repeater (com.intellij.rt.junit)
prepareStreamsAndStart:235, JUnitStarter (com.intellij.rt.junit)
main:54, JUnitStarter (com.intellij.rt.junit)
Bootstrap使用:
createBootstrap:122, RedisClient (org.redisson.client)
<init>:115, RedisClient (org.redisson.client)
create:77, RedisClient (org.redisson.client)
createClient:425, MasterSlaveConnectionManager (org.redisson.connection)
createClient:412, MasterSlaveConnectionManager (org.redisson.connection)
setupMasterEntry:116, MasterSlaveEntry (org.redisson.connection)
setupMasterEntry:112, MasterSlaveEntry (org.redisson.connection)
initSingleEntry:330, MasterSlaveConnectionManager (org.redisson.connection)
<init>:146, MasterSlaveConnectionManager (org.redisson.connection)
<init>:30, SingleConnectionManager (org.redisson.connection)
createConnectionManager:190, ConfigSupport (org.redisson.config)
<init>:68, Redisson (org.redisson)
create:109, Redisson (org.redisson)
testApp:58, AppTest (com.demo.redission)
invokeVirtual:-1, LambdaForm$DMH/0x0000000800c0c400 (java.lang.invoke)
invoke:-1, LambdaForm$MH/0x0000000800c0d800 (java.lang.invoke)
invokeExact_MT:-1, Invokers$Holder (java.lang.invoke)
invokeImpl:154, DirectMethodHandleAccessor (jdk.internal.reflect)
invoke:104, DirectMethodHandleAccessor (jdk.internal.reflect)
invoke:577, Method (java.lang.reflect)
runTest:154, TestCase (junit.framework)
runBare:127, TestCase (junit.framework)
protect:106, TestResult$1 (junit.framework)
runProtected:124, TestResult (junit.framework)
run:109, TestResult (junit.framework)
run:118, TestCase (junit.framework)
runTest:208, TestSuite (junit.framework)
run:203, TestSuite (junit.framework)
doRun:116, TestRunner (junit.textui)
doRun:117, JUnit3IdeaTestRunner (com.intellij.junit3)
doRun:109, TestRunner (junit.textui)
startRunnerWithArgs:38, JUnit3IdeaTestRunner (com.intellij.junit3)
execute:38, IdeaTestRunner$Repeater$1 (com.intellij.rt.junit)
repeat:11, TestsRepeater (com.intellij.rt.execution.junit)
startRunnerWithArgs:35, IdeaTestRunner$Repeater (com.intellij.rt.junit)
prepareStreamsAndStart:235, JUnitStarter (com.intellij.rt.junit)
main:54, JUnitStarter (com.intellij.rt.junit)
future 使用:
handleResult:547, RedisExecutor (org.redisson.command)
checkAttemptPromise:524, RedisExecutor (org.redisson.command)
lambda$execute$4:176, RedisExecutor (org.redisson.command)
accept:-1, RedisExecutor$$Lambda$85/0x0000000800d64c28 (org.redisson.command)
uniWhenComplete:863, CompletableFuture (java.util.concurrent)
tryFire:841, CompletableFuture$UniWhenComplete (java.util.concurrent)
postComplete:510, CompletableFuture (java.util.concurrent)
complete:2147, CompletableFuture (java.util.concurrent)
completeResponse:467, CommandDecoder (org.redisson.client.handler)
handleResult:461, CommandDecoder (org.redisson.client.handler)
decode:340, CommandDecoder (org.redisson.client.handler)
decodeCommand:205, CommandDecoder (org.redisson.client.handler)
decode:144, CommandDecoder (org.redisson.client.handler)
decode:120, CommandDecoder (org.redisson.client.handler)
decodeRemovalReentryProtection:529, ByteToMessageDecoder (io.netty.handler.codec)
callDecode:366, ReplayingDecoder (io.netty.handler.codec)
channelRead:290, ByteToMessageDecoder (io.netty.handler.codec)
invokeChannelRead:444, AbstractChannelHandlerContext (io.netty.channel)
invokeChannelRead:420, AbstractChannelHandlerContext (io.netty.channel)
fireChannelRead:412, AbstractChannelHandlerContext (io.netty.channel)
channelRead:1410, DefaultChannelPipeline$HeadContext (io.netty.channel)
invokeChannelRead:440, AbstractChannelHandlerContext (io.netty.channel)
invokeChannelRead:420, AbstractChannelHandlerContext (io.netty.channel)
fireChannelRead:919, DefaultChannelPipeline (io.netty.channel)
read:166, AbstractNioByteChannel$NioByteUnsafe (io.netty.channel.nio)
processSelectedKey:788, NioEventLoop (io.netty.channel.nio)
processSelectedKeysOptimized:724, NioEventLoop (io.netty.channel.nio)
processSelectedKeys:650, NioEventLoop (io.netty.channel.nio)
run:562, NioEventLoop (io.netty.channel.nio)
run:997, SingleThreadEventExecutor$4 (io.netty.util.concurrent)
run:74, ThreadExecutorMap$2 (io.netty.util.internal)
run:30, FastThreadLocalRunnable (io.netty.util.concurrent)
run:833, Thread (java.lang)
redis 解码
/home/dai/.m2/repository/org/redisson/redisson/3.19.0/redisson-3.19.0-sources.jar!/org/redisson/client/handler/RedisChannelInitializer.java
@Override
protected void initChannel(Channel ch) throws Exception {
initSsl(config, ch);
if (type == Type.PLAIN) {
ch.pipeline().addLast(new RedisConnectionHandler(redisClient));
} else {
ch.pipeline().addLast(new RedisPubSubConnectionHandler(redisClient));
}
ch.pipeline().addLast(
connectionWatchdog,
CommandEncoder.INSTANCE,
CommandBatchEncoder.INSTANCE);
if (type == Type.PLAIN) {
ch.pipeline().addLast(new CommandsQueue());
} else {
ch.pipeline().addLast(new CommandsQueuePubSub());
}
if (pingConnectionHandler != null) {
ch.pipeline().addLast(pingConnectionHandler);
}
if (type == Type.PLAIN) {
ch.pipeline().addLast(new CommandDecoder(config.getAddress().getScheme())); // 解码
} else {
ch.pipeline().addLast(new CommandPubSubDecoder(config));
}
ch.pipeline().addLast(new ErrorsLoggingHandler());
config.getNettyHook().afterChannelInitialization(ch);
}
redission future 回调:
handleResult:547, RedisExecutor (org.redisson.command)
checkAttemptPromise:524, RedisExecutor (org.redisson.command)
lambda$execute$4:176, RedisExecutor (org.redisson.command)
accept:-1, RedisExecutor$$Lambda$86/0x0000000800d64c18 (org.redisson.command)
uniWhenComplete:863, CompletableFuture (java.util.concurrent)
tryFire:841, CompletableFuture$UniWhenComplete (java.util.concurrent)
postComplete:510, CompletableFuture (java.util.concurrent)
complete:2147, CompletableFuture (java.util.concurrent)
completeResponse:467, CommandDecoder (org.redisson.client.handler)
handleResult:461, CommandDecoder (org.redisson.client.handler)
decode:392, CommandDecoder (org.redisson.client.handler)
decodeCommand:205, CommandDecoder (org.redisson.client.handler)
decode:144, CommandDecoder (org.redisson.client.handler)
decode:120, CommandDecoder (org.redisson.client.handler)
decodeRemovalReentryProtection:529, ByteToMessageDecoder (io.netty.handler.codec)
callDecode:366, ReplayingDecoder (io.netty.handler.codec)
channelRead:290, ByteToMessageDecoder (io.netty.handler.codec)
invokeChannelRead:444, AbstractChannelHandlerContext (io.netty.channel)
invokeChannelRead:420, AbstractChannelHandlerContext (io.netty.channel)
fireChannelRead:412, AbstractChannelHandlerContext (io.netty.channel)
channelRead:1410, DefaultChannelPipeline$HeadContext (io.netty.channel)
invokeChannelRead:440, AbstractChannelHandlerContext (io.netty.channel)
invokeChannelRead:420, AbstractChannelHandlerContext (io.netty.channel)
fireChannelRead:919, DefaultChannelPipeline (io.netty.channel)
read:166, AbstractNioByteChannel$NioByteUnsafe (io.netty.channel.nio)
processSelectedKey:788, NioEventLoop (io.netty.channel.nio)
processSelectedKeysOptimized:724, NioEventLoop (io.netty.channel.nio)
processSelectedKeys:650, NioEventLoop (io.netty.channel.nio)
run:562, NioEventLoop (io.netty.channel.nio)
run:997, SingleThreadEventExecutor$4 (io.netty.util.concurrent)
run:74, ThreadExecutorMap$2 (io.netty.util.internal)
run:30, FastThreadLocalRunnable (io.netty.util.concurrent)
run:833, Thread (java.lang)