Việc làm

11/09 · Hồ Chí Minh · Tại văn phòng

Senior Fullstack Engineer (Java + React)

VNGGames · Fullstack Developer

Xem mô tả & ứng tuyển trên ITviecMô tả công việc, lương và ứng tuyển nằm ở ITviec.

10 câu hỏi có thể gặp khi phỏng vấn

Chọn theo kỹ năng và cấp của tin (Java, ReactJS, DevOps & CI/CD). Gợi ý trả lời do Drama Công Ty biên soạn để bạn ôn nhanh, không phải đề của công ty.

  1. 01Bộ nhớ JVM gồm những vùng nào? Garbage Collector hoạt động ra sao và Java có bị memory leak không?Java

    Gợi ý trả lời

    Hai vùng chính: stack (mỗi thread một stack, chứa biến cục bộ và tham chiếu) và heap (chứa object, dùng chung). Ngoài ra có Metaspace chứa thông tin class.

    • GC tìm các object không còn được tham chiếu từ "GC roots" (biến trên stack, field static...) và thu hồi.
    • Heap chia theo thế hệ: object mới nằm ở young generation, sống lâu thì được chuyển lên old generation.
    • G1 là GC mặc định; ZGC hợp khi cần pause rất ngắn với heap lớn.

    Java vẫn leak khi object không dùng nữa mà vẫn còn tham chiếu:

    • Cache hoặc static Map chỉ thêm, không bao giờ xoá.
    • ThreadLocal không remove() trong thread pool.
    • Listener đăng ký mà không huỷ.

    Người phỏng vấn muốn nghe: phân biệt được OutOfMemoryError: Java heap space với lỗi Metaspace, và biết dùng heap dump để tìm ai đang giữ object.

    Ôn thêm câu hỏi Java →
  2. 02Virtual threads trong Java 21 là gì? Khi nào nên dùng và cần lưu ý gì?Java · Senior

    Gợi ý trả lời

    Virtual thread là thread nhẹ do JVM quản lý, được gắn lên một số ít platform thread (carrier). Khi gặp I/O blocking, nó nhả carrier để chạy việc khác, nên bạn có thể có hàng trăm nghìn thread mà vẫn viết code blocking dễ đọc.

    try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
        ids.forEach(id -> executor.submit(() -> callApi(id)));
    }
    
    • Hợp với tải nhiều I/O (gọi DB, HTTP). Không giúp gì với tác vụ nặng CPU.
    • Spring Boot 3.2+ bật bằng spring.threads.virtual.enabled=true.
    • Không đưa virtual thread vào pool: tạo mới cho mỗi task là cách dùng đúng.
    • Giới hạn tài nguyên (connection pool DB) vẫn là giới hạn thật; dùng Semaphore nếu cần.
    • Trên Java 21, blocking bên trong synchronized có thể "pin" carrier; các bản JDK mới hơn đã cải thiện. Cẩn thận với ThreadLocal chứa object lớn.

    Người phỏng vấn muốn nghe: virtual threads tăng throughput, không làm từng request nhanh hơn.

    Ôn thêm câu hỏi Java →
  3. 03So sánh synchronized, volatile, ReentrantLock và ConcurrentHashMap. Bạn tránh race condition thế nào?Java · Senior

    Gợi ý trả lời

    Race condition xảy ra khi nhiều thread đọc-sửa-ghi cùng dữ liệu mà không đồng bộ. Mỗi công cụ giải quyết một phần:

    • volatile: đảm bảo visibility (thread khác thấy giá trị mới nhất), nhưng không làm count++ thành atomic.
    • synchronized: vừa loại trừ lẫn nhau vừa đảm bảo visibility (quan hệ happens-before).
    • ReentrantLock: như synchronized nhưng có tryLock với timeout, lock có thể ngắt, nhiều Condition.
    • AtomicInteger/LongAdder: đếm không cần lock.
    • ConcurrentHashMap: thread-safe với độ tranh chấp thấp. Dùng compute/merge/putIfAbsent cho thao tác kép, đừng get rồi put.

    Hay sai: dùng Collections.synchronizedMap rồi duyệt map mà không lock, hoặc kiểm tra if (!map.containsKey(k)) map.put(k, v) trên map đồng thời: hai bước riêng lẻ vẫn bị chen ngang. Cách tốt nhất vẫn là giảm state dùng chung (object bất biến, mỗi thread một bản).

    Ôn thêm câu hỏi Java →
  4. 04React Server Components là gì? Trong Next.js App Router, khi nào dùng Server Component và khi nào cần "use client"?ReactJS · Senior

    Gợi ý trả lời

    Server Component chạy trên server (lúc build hoặc lúc request), có thể await dữ liệu trực tiếp từ DB hoặc API, và không gửi JavaScript của nó xuống trình duyệt. Trong App Router, component mặc định là Server Component.

    • Dùng Server Component cho: lấy dữ liệu, render nội dung tĩnh, dùng secret hoặc thư viện nặng chỉ cần ở server.
    • Cần "use client" khi dùng state, effect, sự kiện (onClick), API trình duyệt (window, localStorage).
    • "use client" đánh dấu ranh giới: mọi module được import từ file đó đều vào bundle client.
    • Server Component có thể truyền Server Component khác vào Client Component qua children.
    • Props truyền từ server sang client phải serialize được (không truyền hàm thường; Server Action thì được).

    Hay sai: đặt "use client" ở layout gốc, biến cả app thành client và mất lợi ích. Hãy đẩy phần tương tác xuống các component lá.

    Ôn thêm câu hỏi ReactJS →
  5. 05Một màn hình React (bảng dữ liệu lớn, ô tìm kiếm) bị giật lag. Bạn tìm và xử lý thế nào?ReactJS · Senior

    Gợi ý trả lời

    Đo trước: React DevTools Profiler (bật "Highlight updates" và xem component nào render nhiều, tốn bao lâu) và tab Performance của Chrome để tìm long task.

    Các hướng xử lý thường gặp:

    • Giảm phạm vi render: đưa state xuống gần nơi dùng; tách component; memo các hàng của bảng với props ổn định.
    • Virtualization cho list hoặc bảng dài: chỉ render các dòng đang hiện (TanStack Virtual, react-window).
    • Ưu tiên cập nhật: useDeferredValue hoặc useTransition để ô input phản hồi ngay, còn việc lọc bảng chạy sau và có thể bị ngắt.
    • Tính toán nặng: useMemo, hoặc chuyển sang Web Worker.
    • Bundle lớn: lazy() và Suspense để tách code theo route hoặc theo modal.

    Người phỏng vấn muốn nghe: bạn tìm ra nguyên nhân cụ thể (render thừa, DOM quá nhiều, JS nặng) rồi mới chọn kỹ thuật, không rải useMemo khắp nơi.

    Ôn thêm câu hỏi ReactJS →
  6. 06Production đang lỗi 5xx tăng vọt sau một lần deploy. Bạn xử lý thế nào?DevOps & CI/CD · Senior

    Gợi ý trả lời

    Ưu tiên khôi phục dịch vụ trước, tìm nguyên nhân gốc sau.

    1. Xác nhận phạm vi qua dashboard: endpoint nào, từ lúc nào, có trùng thời điểm deploy không.
    2. Nếu nghi deploy: rollback ngay (kubectl rollout undo, hoặc revert trong GitOps) thay vì sửa nóng.
    3. Thông báo kênh sự cố, chỉ định người điều phối, ghi lại mốc thời gian.
    4. Sau khi ổn định: so sánh log, trace, diff cấu hình giữa hai phiên bản.
    5. Viết postmortem không đổ lỗi, có hành động phòng ngừa (thêm test, canary, alert).

    Người phỏng vấn muốn nghe: bình tĩnh, có thứ tự, biết giảm thiệt hại trước, và rút kinh nghiệm thành thay đổi quy trình.

    Ôn thêm câu hỏi DevOps & CI/CD →
  7. 07Một service Spring Boot trên production đột nhiên chậm, CPU cao hoặc bị OOM. Bạn điều tra thế nào?Java · Senior

    Gợi ý trả lời

    Đi từ số liệu đến bằng chứng, đừng đoán rồi sửa.

    1. Xem metrics (Actuator, Micrometer): latency, số request, heap, GC pause, connection pool đang chờ, thời gian gọi DB và API ngoài.
    2. CPU cao: lấy thread dump vài lần cách nhau vài giây (jcmd <pid> Thread.print hoặc jstack), tìm thread luôn RUNNABLE ở cùng chỗ. Có thể là vòng lặp, regex xấu, hoặc GC chạy liên tục.
    3. Chậm mà CPU thấp: thread đang chờ: hết connection DB, lock, gọi API ngoài không có timeout.
    4. OOM hoặc heap tăng dần: bật -XX:+HeapDumpOnOutOfMemoryError, mở heap dump bằng Eclipse MAT, xem ai giữ nhiều bộ nhớ nhất.
    5. Java Flight Recorder (jcmd <pid> JFR.start) cho profile chi phí thấp, dùng được trên production.

    Người phỏng vấn muốn nghe: có quy trình rõ ràng, biết cả cách giảm thiệt hại tạm thời (rollback, scale) trước khi tìm nguyên nhân gốc.

    Ôn thêm câu hỏi Java →
  8. 08Hai người cùng đặt mua sản phẩm cuối cùng trong kho. Bạn xử lý cập nhật đồng thời trong JPA thế nào?Java · Senior

    Gợi ý trả lời

    Đây là bài toán lost update. Có hai hướng chính, chọn theo mức độ tranh chấp:

    • Optimistic locking: thêm field @Version. Khi update, Hibernate kèm điều kiện where version = ?; nếu người khác đã sửa trước, bạn nhận OptimisticLockException và có thể retry hoặc báo lỗi. Hợp khi tranh chấp ít.
    • Pessimistic locking: @Lock(LockModeType.PESSIMISTIC_WRITE) sinh SELECT ... FOR UPDATE, giữ khoá đến hết transaction. Hợp khi tranh chấp nhiều, đổi lại throughput giảm và có nguy cơ deadlock.
    • Đơn giản nhất cho tồn kho: update có điều kiện ngay trong DB:
    UPDATE product SET stock = stock - 1
    WHERE id = ? AND stock > 0;
    

    Kiểm tra số dòng bị ảnh hưởng: bằng 0 nghĩa là hết hàng.

    Hay sai: dùng synchronized trong code Java. Nó vô dụng khi chạy nhiều instance, và cũng không bảo vệ được dữ liệu ở DB.

    Ôn thêm câu hỏi Java →
  9. 09Dependency Injection trong Spring là gì? Vì sao nên dùng constructor injection thay cho @Autowired trên field?Java

    Gợi ý trả lời

    IoC container của Spring tạo và quản lý các bean, rồi "tiêm" phụ thuộc vào class cần dùng, thay vì class tự new. Nhờ vậy code ít phụ thuộc cứng, dễ thay implementation và dễ test.

    Constructor injection được khuyên dùng vì:

    • Field có thể là final, object luôn ở trạng thái đầy đủ sau khi tạo.
    • Test unit không cần Spring: chỉ cần new OrderService(mockRepo).
    • Constructor quá nhiều tham số là dấu hiệu class đang ôm nhiều việc.
    • Class chỉ có một constructor thì không cần ghi @Autowired.

    Nên nói thêm về scope: mặc định bean là singleton (một instance cho cả context), ngoài ra có prototype, request, session.

    Hay sai: để state thay đổi được (ví dụ biến đếm, list) trong bean singleton. Nhiều request chạy song song sẽ dùng chung và gây race condition.

    Ôn thêm câu hỏi Java →
  10. 10Vì sao bạn muốn rời công ty hiện tại?Câu hỏi hành vi & văn hoá

    Gợi ý trả lời

    Trả lời thật nhưng hướng về phía trước: nói điều bạn đang tìm kiếm, không kể xấu nơi cũ.

    Lý do chấp nhận được: muốn thử thách mới, muốn làm sản phẩm, dự án kết thúc, công ty tái cấu trúc, thu nhập chưa tương xứng (nói khéo).

    Câu mẫu: "Em đã làm 2 năm ở dự án outsourcing, học được nhiều về quy trình và làm việc với khách nước ngoài. Giờ em muốn gắn bó lâu dài với một sản phẩm để thấy được tác động của những gì mình làm, và vị trí bên mình đúng hướng đó."

    Hay sai: chê sếp, chê đồng nghiệp, kể chuyện drama. Người phỏng vấn sẽ nghĩ bạn cũng sẽ nói về công ty họ như vậy. Nếu nhảy việc nhiều, chuẩn bị lời giải thích cho từng lần.

    Ôn thêm câu hỏi Câu hỏi hành vi & văn hoá →

Bạn đã phỏng vấn ở VNGGames?

Kể lại các vòng và câu hỏi đã gặp (ẩn danh) để người sau ôn đúng trọng tâm.

Chia sẻ kinh nghiệm phỏng vấn