Farzad Afi Logo

FarzadAfi

آموزش تخصصی برنامه نویسی

Stop Leak, Close JDBC Resources

📖توضیحات درس

🎥 این ویدیو قسمت سی‌وهشتم از بوت‌کمپ رایگان جاواست. 📚 JDBC – جلوگیری از نشت منابع با بستن Connection، Statement و ResultSet در این جلسه یکی از موضوعات بسیار مهم و کاربردی در کار با JDBC را بررسی می‌کنیم: مدیریت صحیح منابع و جلوگیری از نشت آن‌ها. اگر منابعی مثل Connection، Statement یا ResultSet به‌موقع بسته نشوند، می‌توانند باعث مصرف بی‌رویه حافظه و حتی از کار افتادن اپلیکیشن شوند. در این ویدیو بررسی می‌کنیم: - چرا بستن منابع JDBC اهمیت زیادی دارد - در چه شرایطی منابع دچار نشت (leak) می‌شوند - روش صحیح بستن Connection، Statement و ResultSet - پیاده‌سازی این مفاهیم در یک پروژه واقعی - نکات مهم و ترفندهایی برای مدیریت بهینه منابع 📌 کدهای این جلسه داخل GitHub قرار گرفته و می‌توانی بررسی‌شان کنی: https://github.com/farzadafi/ProgrammingByFarzadAfi/tree/master/02_jdbc/02_library/v3 💬 گروه پرسش و پاسخ تلگرام: @programmingByFarzadAfi 💬 گروه پرسش و پاسخ بله: @programming_by_farzadafi هر سوالی داشتی، توی گروه بپرس؛ من یا مربی‌های گروه حتماً راهنمایی‌ات می‌کنیم 🌱 🎯 بوت‌کمپ رایگان جاوا – آموزش پروژه‌محور برای یادگیری عمیق و ورود به بازار کار
00:47:49🎯رایگان

📄جزوه

مفاهیم کلیدی

  • JDBC Resources
    منابعی مانند Connection ،Statement و ResultSet که برای برقراری ارتباط و اجرای کوئری در پایگاه داده استفاده می‌شوند و باید پس از اتمام کار حتماً بسته شوند.

  • Memory Leak (نشت حافظه)
    اتفاقی که وقتی رخ می‌دهد که برنامه منابعی را اشغال کرده اما پس از اتمام کار آن‌ها را آزاد نمی‌کند؛ این موضوع در درازمدت باعث پر شدن حافظه و کندی یا کرش کردن برنامه می‌شود.

  • Idle Connection (اتصال بیکار)
    اتصالی که به دیتابیس باز شده اما هیچ کوئری یا دستوری را اجرا نمی‌کند. این اتصالات همچنان منابع سرور (مانند RAM و CPU) را مصرف می‌کنند.

  • Database Session
    شاهراه‌هایی که از سمت برنامه به پایگاه داده (مثلاً PostgreSQL) باز می‌شوند تا عملیات مورد نظر انجام شود. تعداد این سشن‌ها در دیتابیس محدود است.

  • Database Cursor
    منابعی در سمت پایگاه داده که برای پیمایش روی نتایج کوئری‌ها استفاده می‌شوند. عدم بستن ResultSet می‌تواند منجر به باز ماندن کرسرها و رسیدن به سقف مجاز آن‌ها شود.

  • Garbage Collector (GC)
    بخشی از JVM که وظیفه پاک‌سازی اشیاء بدون استفاده در حافظه RAM را دارد، اما لزوماً بلافاصله منابع خارجی مثل سشن‌های دیتابیس را آزاد نمی‌کند.

  • Connection Pooling
    مکانیزمی که در آن مجموعه‌ای از کانکشن‌ها از قبل ساخته شده و مدیریت می‌شوند تا به جای ساخت و حذف مداوم، از آن‌ها دوباره استفاده شود که باعث بهبود پرفورمنس می‌شود.

نکات مهم مصاحبه‌ای

  • چرا باید منابع JDBC را به صورت دستی Close کنیم؟
    زیرا تکیه بر Garbage Collector برای بستن منابع دیتابیسی اشتباه است. باز ماندن این منابع باعث اشغال سشن‌ها، مصرف بیهوده RAM و CPU در سرور و در نهایت نشت حافظه می‌شود.

  • ترتیب صحیح بستن منابع JDBC به چه صورت است؟
    بهترین روش این است که منابع را به صورت عکسِ زمان ایجاد، ببندیم. یعنی ابتدا ResultSet ، سپس Statement (یا PreparedStatement) و در نهایت Connection.

  • اگر فقط Connection را ببندیم و ResultSet باز بماند چه اتفاقی می‌افتد؟
    در برخی دیتابیس‌ها و در حالت استفاده از Connection Pooling ، ممکن است کرسرهای دیتابیس باز بمانند و پس از مدتی با خطای "حداکثر تعداد کرسرها" مواجه شوید، زیرا منابع سمت سرور آزاد نشده‌اند.

  • تأثیر Idle Connection بر روی دیتابیس چیست؟
    حتی اگر یک اتصال بیکار باشد، طبق بررسی‌های فنی هر اتصال می‌تواند به طور میانگین بین ۱.۵ تا ۱۰ مگابایت (بسته به عملیات قبلی) از حافظه RAM سرور را اشغال کند.

مثال یا سناریوی کاربردی

تصور کنید برنامه‌ای دارید که ۲۰۰۰ اتصال به دیتابیس باز می‌کند اما هیچ‌کدام را نمی‌بندد. با ابزارهایی مثل VisualVM مشاهده خواهید کرد که مصرف حافظه Heap مدام بالا می‌رود. در سمت دیتابیس نیز لیست سشن‌ها نشان‌دهنده ۲۰۰۰ اتصال در وضعیت Idle است.

برای حل این مشکل، باید متدی برای بستن منابع (Clean-up) بنویسیم. برای مثال در یک متد save :

public int save(User user) {
    Connection connection = null;
    PreparedStatement ps = null;
    int result = -1;
    
    try {
        connection = JDBCConnection.getConnection();
        ps = connection.prepareStatement("INSERT INTO users ...");
        // اجرای کوئری
        result = ps.executeUpdate();
    } finally {
        // بستن منابع در بخش نهایی برای امنیت کامل
        if (ps != null) ps.close();
        if (connection != null) connection.close();
    }
    return result;
}

در این سناریو، به محض اتمام کار، منابع آزاد شده و سشن‌های دیتابیس بسته می‌شوند تا برنامه دچار اختلال نشود.

بیشتر بدانید

  • تکنیک Extract Method: برای جلوگیری از تکرار کد بستن منابع در همه متدها، بهتر است یک متد کمکی مثل closeResources بسازید که انواع منابع را به عنوان ورودی گرفته و آن‌ها را ببندد.
  • Import Static: در Java می‌توانید متدهای استاتیک کلاس‌های ابزاری (Utility) را به صورت import static تعریف کنید تا بدون نوشتن نام کلاس، مستقیماً از متدها استفاده کنید.
  • نکته در IntelliJ: استفاده از قابلیت Refactor > Extract Method به شما کمک می‌کند کدهای تکراری برای بستن منابع را به سرعت به یک متد مجزا تبدیل کنید.
  • نکته امنیتی: همیشه بستن منابع را در بلوک‌هایی انجام دهید که از اجرای آن‌ها اطمینان دارید (مانند finally) تا حتی در صورت بروز خطا، نشت حافظه رخ ندهد.