ওভাররাইডিং অবজেক্ট.ফাইনালাইজ () আসলেই খারাপ?


34

ওভাররাইডিংয়ের বিরুদ্ধে প্রধান দুটি যুক্তি Object.finalize()হ'ল:

  1. কখন ডাকা হবে তা আপনি সিদ্ধান্ত নিতে পারবেন না।

  2. একেবারেই কল নাও হতে পারে।

যদি আমি এটি সঠিকভাবে বুঝতে পারি তবে আমি মনে করি না যে এগুলি Object.finalize()এত ঘৃণা করার পক্ষে যথেষ্ট উপযুক্ত কারণ ।

  1. কোনও বস্তুর অবনতি করার সঠিক সময় কখন বিকাশকারী নয়, তা নির্ধারণ করা ভিএম বাস্তবায়ন এবং জিসির উপর নির্ভর করে। কখন Object.finalize()ডাকা হবে তা সিদ্ধান্ত নেওয়া কেন জরুরি ?

  2. সাধারণত, এবং আমি ভুল হলে আমাকে সংশোধন করুন, Object.finalize()জিসি চালানোর সুযোগ পাওয়ার আগে অ্যাপ্লিকেশনটি বন্ধ হয়ে যাওয়ার একমাত্র সময়টি বলা হত না। যাইহোক, অ্যাপ্লিকেশনটির প্রক্রিয়া এটির সাথে শেষ হয়ে গেলে বস্তুটি যাইহোক হ্রাস পাবে। সুতরাং কল করা Object.finalize()হয়নি কারণ এটি কল করার প্রয়োজন ছিল না। কেন বিকাশকারী যত্ন করবেন?

যতবার আমি নিজে হাতে বন্ধ করতে হবে এমন জিনিসগুলি ব্যবহার করছি (ফাইল হ্যান্ডলগুলি এবং সংযোগের মতো), আমি খুব হতাশ হয়ে পড়েছি। কোনও জিনিসের বাস্তবায়ন হয়েছে কিনা তা আমাকে নিয়মিত যাচাই করতে হবে close()এবং আমি নিশ্চিত যে অতীতে কিছু পয়েন্টে আমি এর কয়েকটি কল মিস করেছি। close()বাস্তবায়নটি স্থাপন করে এই বিষয়গুলি নিষ্পত্তি করতে কেবল ভিএম এবং জিসির কাছে রেখে দেওয়া কেন সহজ এবং নিরাপদ নয় Object.finalize()?


1
এছাড়াও নোট করুন: জাভা ১.০ যুগের অনেকগুলি এপিআইয়ের মতো থ্রেড সিনটিক্সগুলি finalize()কিছুটা গণ্ডগোল করে। আপনি যদি কখনও এটিকে বাস্তবায়ন করেন তবে নিশ্চিত করুন যে এটি একই বস্তুর অন্য সমস্ত পদ্ধতির সাথে থ্রেড-নিরাপদ।
বিলc.cn

2
আপনি যখন শুনছেন লোকেদের চূড়ান্তরূপী খারাপ, তাদের অর্থ এই নয় যে আপনার প্রোগ্রামটি যদি তা থাকে তবে কাজ করা বন্ধ হয়ে যাবে; তাদের অর্থ চূড়ান্তকরণের পুরো ধারণাটি বেশ বেহুদা।
ব্যবহারকারী 253751

1
এই প্রশ্নে +1। নীচের বেশিরভাগ উত্তরগুলি জানিয়েছে যে ফাইল বর্ণনাকারীর মতো সংস্থানগুলি সীমিত এবং সেগুলি ম্যানুয়ালি সংগ্রহ করা উচিত। মেমরির ক্ষেত্রেও একই ছিল / সত্য তাই আমরা যদি মেমরি সংগ্রহের ক্ষেত্রে কিছুটা বিলম্ব স্বীকার করি তবে ফাইল বর্ণনাকারী এবং / অথবা অন্যান্য সংস্থাগুলির জন্য কেন এটি গ্রহণ করা হচ্ছে না?
mbonnin

আপনার শেষ অনুচ্ছেদে সম্বোধন করে, আপনি ফাইলের হ্যান্ডলগুলি এবং সংযোগের মতো ক্লোজিং জিনিসগুলি আপনার পক্ষে খুব অল্প প্রচেষ্টা করে পরিচালনা করতে জাভাতে রেখে যেতে পারেন। রিসোর্স ব্লকটি ব্যবহার করে দেখুন - এটি ইতিমধ্যে উত্তর এবং মন্তব্যে আরও কয়েকবার উল্লেখ করা হয়েছে, তবে আমার মনে হয় এটি এখানে রাখার মতো। এর জন্য ওরাকল টিউটোরিয়ালটি docs.oracle.com/javase/tutorial/essential/exception/…-
জিউটার্নগ

উত্তর:


45

আমার অভিজ্ঞতায়, ওভাররাইডের জন্য একটি এবং একমাত্র কারণ রয়েছে Object.finalize()তবে এটি খুব ভাল কারণ :

ত্রুটি লগিং কোড স্থাপন করার জন্য finalize()যা আপনি যদি কখনও অনুরোধ করতে ভুলে যান তবে আপনাকে सूचित করে close()

স্থিতিশীল বিশ্লেষণ কেবল তুচ্ছ ব্যবহারের পরিস্থিতিগুলিতেই বাদ পড়তে পারে এবং অন্য উত্তরে উল্লিখিত সংকলক সতর্কতাগুলির মধ্যে এমন কিছু বিষয়গুলির মধ্যে এমন সরল দৃষ্টিভঙ্গি রয়েছে যা অ-তুচ্ছ কিছু করার জন্য আপনাকে আসলে এগুলি অক্ষম করতে হবে। (আমি জানি বা আমি কখনও শুনেছি এমন কোনও প্রোগ্রামারের চেয়ে আমার আরও বেশি সতর্কতা সক্ষম হয়েছে তবে আমার কাছে বোকা সতর্কতা সক্ষম করা হয়নি))

চূড়ান্তকরণ এটি নিশ্চিত করার জন্য একটি উপযুক্ত ব্যবস্থা বলে মনে হতে পারে যে সংস্থানগুলি অনির্বাচিত না হয় তবে বেশিরভাগ লোক একে সম্পূর্ণ ভুল উপায়ে দেখে: তারা একে বিকল্প ফ্যালব্যাক প্রক্রিয়া হিসাবে বিবেচনা করে, একটি "দ্বিতীয় সুযোগ" সুরক্ষাকারী যা স্বয়ংক্রিয়ভাবে সংরক্ষণ করবে তারা যে সম্পদ ভুলে গিয়েছিল তা নিষ্পত্তি করে দিন। এটা মৃত ভুল । যে কোনও নির্দিষ্ট কাজ করার একটি মাত্র উপায় থাকতে হবে: হয় আপনি সর্বদা সমস্ত কিছু বন্ধ করে দেন, বা চূড়ান্তকরণ সর্বদা সবকিছু বন্ধ করে দেয়। তবে চূড়ান্তকরণ যেহেতু অবিশ্বাস্য তাই চূড়ান্তকরণ এটি হতে পারে না।

সুতরাং, সেখানে এই স্কিম যা আমি কল আবশ্যিক নিষ্পত্তি , এবং এটি শর্তাধীন যে প্রোগ্রামার জন্য দায়ী সবসময় স্পষ্টভাবে সবকিছু বন্ধ যা কার্যকরী Closeableবা AutoCloseable। (চেষ্টা সহ-সংস্থানসমূহের বিবৃতিটি এখনও স্পষ্ট সমাপ্তির হিসাবে গণনা করে)) অবশ্যই, প্রোগ্রামারটি ভুলে যেতে পারে, তাই এখানে চূড়ান্তকরণ কার্যকর হয়, তবে ম্যাজিক পরী হিসাবে নয় যা শেষ পর্যন্ত ম্যাজিকভাবে জিনিসগুলি তৈরি করবে: যদি চূড়ান্তকরণ আবিষ্কার হয় যে close()আহ্বান করা হয়নি, এটি নাএটিকে আহ্বান করার চেষ্টা করুন, অবাকভাবে কারণ কারণ সেখানে (গাণিতিক নিশ্চিততার সাথে) এন00 বি প্রোগ্রামারদের সৈন্যদল থাকবে যারা এই কাজটি করার জন্য এটির উপর নির্ভর করবে যে তারা খুব অলস বা খুব অনুপস্থিত মনোযোগী ছিল না। সুতরাং, বাধ্যতামূলক নিষ্পত্তির সাথে সাথে, যখন চূড়ান্তকরণ আবিষ্কার হয় যা close()আহ্বান করা হয় নি, এটি একটি উজ্জ্বল লাল ত্রুটি বার্তা লগ করে, বড় ধরণের চর্বিযুক্ত সমস্ত মূলধনযুক্ত প্রোগ্রামারকে তার স্ট্রিং - তার জিনিসগুলি ঠিক করতে বলে।

অতিরিক্ত সুবিধা হিসাবে, গুজবটিতে রয়েছে যে "জেভিএম একটি তুচ্ছ চূড়ান্তকরণ পদ্ধতি () অবজ্ঞা করবে (উদাহরণস্বরূপ যা কেবল কিছুই না করে ফিরে আসে, অবজেক্ট শ্রেণিতে সংজ্ঞায়িত পদ্ধতিটির মতো)", তাই বাধ্যতামূলক নিষ্পত্তি দিয়ে আপনি সমস্ত চূড়ান্তকরণ এড়াতে পারবেন আপনার পুরো সিস্টেমে ওভারহেড ( এই ওভারহেডটি কতটা ভয়ঙ্কর তার তথ্যের জন্য আলিপের উত্তর দেখুন ) আপনার finalize()পদ্ধতিটি এভাবে কোড করে:

@Override
protected void finalize() throws Throwable
{
    if( Global.DEBUG && !closed )
    {
        Log.Error( "FORGOT TO CLOSE THIS!" );
    }
    //super.finalize(); see alip's comment on why this should not be invoked.
}

এর পিছনে ধারণাটি Global.DEBUGহ'ল একটি static finalপরিবর্তনশীল যার মান সংকলনের সময় জানা যায়, সুতরাং যদি এটি হয় falseতবে সংকলক পুরো ifবিবৃতিটির জন্য কোনও কোডই নির্গত করবে না , যা এটি একটি তুচ্ছ (খালি) চূড়ান্তরূপে পরিণত করবে, যা পরিবর্তিত হয় মানে আপনার ক্লাসটিকে এমন চিকিত্সা করা হবে যেন তার চূড়ান্তকরণকারী নেই। (সি # এ এটি একটি দুর্দান্ত #if DEBUGব্লক দিয়ে করা হবে , তবে আমরা কী করতে পারি, এটি জাভা, যেখানে আমরা মস্তিষ্কে অতিরিক্ত ওভারহেড সহ কোডটিতে সুস্পষ্ট সরলতা প্রদান করি))

ডট নেট-এ রিসোর্সগুলি নিষ্পত্তি করার বিষয়ে অতিরিক্ত আলোচনার সাথে বাধ্যতামূলক নিষ্পত্তি সম্পর্কে আরও: এখানে মাইকেল: র: বাধ্যতামূলক নিষ্পত্তি বনাম "ডিসপোজ-ডিসপোজিং" জঘন্য আচরণ


2
@ মাইকনাকিস ভুলে যাবেন না, দ্বিতীয়বার বলা হয়ে থাকলে ক্লোজযোগ্য কিছুই না করার সংজ্ঞা দেওয়া হয়েছে: ডকস.অরাকল . com / javase / 7 / docs / api / java / io / ক্লোজেবল html । আমি স্বীকার করি যে আমার ক্লাস দু'বার বন্ধ হয়ে গেলে আমি মাঝে মধ্যে একটি সতর্কতা লগ করেছি, তবে প্রযুক্তিগতভাবে আপনি এটি করার কথাও মনে করেন না। প্রযুক্তিগতভাবে যদিও, ক্লোজবেলে .close () কল করা একাধিকবার বৈধ is
প্যাট্রিক এম

1
আপনি আমাদের পরীক্ষায় বিশ্বাস রাখেন বা আপনি নিজের পরীক্ষার উপর বিশ্বাস রাখেন না সে সম্পর্কে @ সমস্ত কিছু এগুলি ফুটে উঠেছে। আপনি আপনার টেস্টিং বিশ্বাস করতে পারি না, তাহলে নিশ্চিত করুন, এগিয়ে যান এবং করতে চূড়ান্ত ওভারহেড কষ্ট ভোগ এছাড়াও close() , ধরো যদি। আমি বিশ্বাস করি যে আমার পরীক্ষায় যদি বিশ্বাসযোগ্য না হয় তবে আমি আরও ভালভাবে সিস্টেমটি উত্পাদন করতে ছাড়ি না।
মাইক নাকিস

3
@ মাইক, if( Global.DEBUG && ...নির্মাণের জন্য কাজটি যাতে জেভিএম finalize()পদ্ধতিটিকে তুচ্ছ হিসাবে অগ্রাহ্য করবে , Global.DEBUGসংকলন সময়ে সেট করতে হবে (ইনজেকশন ইত্যাদির বিপরীতে) তাই নিম্নলিখিতটি ডেড কোড হবে। যদি সুপার ক্লাসের তুচ্ছ হয় তবুও যদি super.finalize()জেভিএম-এর পক্ষে এটি অ-তুচ্ছ হিসাবে বিবেচনা করা যায় (তবে Global.DEBUGকমপক্ষে হটস্পট ১.৮-তে নির্বিশেষে এর মান নির্বিশেষে) যদি ইফ ব্লকের বাইরে কল করাও যথেষ্ট #finalize()!
14:44 এ আলিপ করুন

1
@ মাইকে আমি ভয় পাই যে এটাই ঘটনা। আপনি যে নিবন্ধটি লিঙ্ক করেছেন তাতে পরীক্ষার (কিছুটা পরিবর্তিত সংস্করণ) দিয়ে এটি পরীক্ষা করেছি এবং ভারবস জিসি আউটপুট (আশ্চর্যজনকভাবে দুর্বল পারফরম্যান্সের সাথে) এটি নিশ্চিত করেছে যে অবজেক্টগুলি বেঁচে / পুরানো প্রজন্মের স্পেসে অনুলিপি করা হয়েছে এবং পেতে সম্পূর্ণ হিপ জিসি প্রয়োজন দূর করা.
আলিপ

1
যা প্রায়শই উপেক্ষা করা হয়, এটি প্রত্যাশিত বস্তুর সংগ্রহের ঝুঁকি যা চূড়ান্তকরণে নিখরচায় সংস্থানকে একটি অত্যন্ত বিপজ্জনক পদক্ষেপ করে তোলে। জাভা 9 এর পূর্বে, কোনও ফাইনালাইজারটি ব্যবহারের সময় রিসোর্সটি বন্ধ করবে না তা নিশ্চিত হওয়ার একমাত্র উপায় হ'ল সংস্থানটি ব্যবহার করা হবে এবং উত্সটি ব্যবহার করে পদ্ধতি (গুলি) উভয় ক্ষেত্রেই বস্তুটির সাথে সিঙ্ক্রোনাইজ করা। এই জন্য এটি কাজ করে java.io। যদি সেই ধরণের থ্রেড সুরক্ষা ইচ্ছার তালিকায় না থাকে, তবে এটি ওভারহেডকে প্ররোচিত করে finalize()
হোলার

28

যতবার আমি নিজে হাতে বন্ধ করতে হবে এমন জিনিসগুলি ব্যবহার করছি (ফাইল হ্যান্ডলগুলি এবং সংযোগের মতো), আমি খুব হতাশ হয়ে পড়েছি। [...] close()বাস্তবায়নটি স্থাপন করে এই বিষয়গুলি নিষ্পত্তি করতে কেবল ভিএম এবং জিসির কাছে রেখে দেওয়া কেন সহজ এবং নিরাপদ নয় Object.finalize()?

কারণ ফাইল হ্যান্ডেলগুলি এবং সংযোগগুলি ( এটি লিনাক্স এবং পসিক্স সিস্টেমে ফাইল বর্ণনাকারী ) বেশ দুষ্প্রাপ্য সংস্থান (আপনার কিছু সিস্টেমে এটির 256 বা অন্য কিছুতে 16384 পর্যন্ত সীমাবদ্ধ থাকতে পারে; সেট্রলিট (2) দেখুন )। এ জাতীয় সীমিত সংস্থান নিঃসরণ এড়াতে জিসিকে প্রায়শই পর্যাপ্ত পরিমাণে ডাকা হবে (বা সঠিক সময়ে) বলা হবে এমন কোনও গ্যারান্টি নেই। এবং যদি জিসিকে পর্যাপ্ত পরিমাণে না বলা হয় (বা চূড়ান্তকরণ সঠিক সময়ে চালানো হয় না) তবে আপনি সেই (সম্ভবত কম) সীমাতে পৌঁছে যাবেন।

চূড়ান্তকরণ জেভিএম-এর একটি "সেরা প্রচেষ্টা" জিনিস। এটি ডাকা হতে পারে না, বা বেশ দেরিতে ডাকা হতে পারে ... বিশেষত, আপনার যদি প্রচুর র‍্যাম থাকে বা আপনার প্রোগ্রামটি প্রচুর পরিমাণে বরাদ্দ না করে (বা তাদের বেশিরভাগই যদি কিছু পুরানো কাছে পাঠানোর আগে মারা যায় তবে একটি অনুলিপি জেনারাল জিসি দ্বারা প্রজন্মের), জিসিটি খুব কমই বলা যেতে পারে, এবং চূড়ান্তকরণগুলি খুব বেশি সময় চলতে পারে না (বা এমনকি এটি মোটেও চালাতে পারে না)।

সুতরাং closeসম্ভব হলে স্পষ্টভাবে ফাইল বর্ণনাকারী ফাইল করুন। আপনি যদি এগুলি ফাঁস হতে ভয় পান তবে চূড়ান্তকরণটি মূল হিসাবে নয়, অতিরিক্ত পরিমাপ হিসাবে ব্যবহার করুন।


7
আমি যুক্ত করব যে কোনও ফাইল বা সকেটে স্ট্রিম বন্ধ করা সাধারণত এটিকে ফ্লাশ করে। স্ট্রিমগুলি অকারণে খোলা রেখে বিদ্যুৎ চলে যাওয়ার সাথে সাথে ডেটা হ্রাস হওয়ার ঝুঁকি বাড়ায়, একটি সংযোগ

2
প্রকৃতপক্ষে, অনুমোদিত ফাইলডিসিপেক্টরগুলির সংখ্যা কম থাকতে পারে, এটি সত্যিকারের স্টিকি পয়েন্ট নয়, কারণ কোনও একটি এটি অন্তত জিসির জন্য একটি সংকেত হিসাবে ব্যবহার করতে পারে । এটি আসলেই সমস্যাযুক্ত জিনিসটি হ'ল) ​​জিসির কাছে সম্পূর্ণ অপ্রতিরোধ্য, নন-জিসি-পরিচালিত সংস্থানগুলি এতে কতটা ঝুলিয়ে রাখে, এবং খ) সেগুলি অনেকগুলি অনন্য, তাই অন্যরা অবরুদ্ধ বা অস্বীকৃত হতে পারে।
ডিসিপ্লিকেটর

2
এবং আপনি যদি কোনও ফাইল উন্মুক্ত রেখে দেন তবে এটি ব্যবহার করে অন্য কারও সাথে হস্তক্ষেপ করতে পারে। (উইন্ডোজ 8 এক্সপিএস ভিউয়ার, আমি আপনার দিকে
তাকাচ্ছি

2
"আপনি যদি [ফাইল বর্ণনাকারীদের] ফাঁস হতে ভয় পান, তবে চূড়ান্তকরণকে মূল ব্যবস্থা হিসাবে নয়, অতিরিক্ত পরিমাপ হিসাবে ব্যবহার করুন।" এই বক্তব্যটি আমার কাছে মজাদার মনে হচ্ছে। আপনি যদি আপনার কোডটি ভালভাবে ডিজাইন করেন তবে আপনার কি সত্যই রিডানড্যান্ট কোডটি প্রবর্তন করা উচিত যা একাধিক জায়গাতে ক্লিনআপ ছড়িয়ে দেয়?
মুচাহো

2
@ বাসাইলস্টারিঙ্কেভিচ আপনার বক্তব্যটি একটি আদর্শ বিশ্বে, হ্যাঁ, অতিরিক্ত কাজটি খারাপ, তবে বাস্তবে আপনি যেখানে সমস্ত প্রাসঙ্গিক দিকটির পূর্বাভাস দিতে পারবেন না, দুঃখের চেয়ে আরও নিরাপদ থাকবেন?
মুচাহো

13

বিষয়টি এইভাবে দেখুন: আপনার কেবল কোডটি লিখতে হবে যা (ক) সঠিক (অন্যথায় আপনার প্রোগ্রামটি সম্পূর্ণ ভুল) এবং (খ) প্রয়োজনীয় (অন্যথায় আপনার কোডটি অনেক বড়, যার অর্থ বেশি র‌্যাম প্রয়োজনীয়, আরও চক্র ব্যয় করা অকেজো জিনিস, এটি বোঝার আরও প্রচেষ্টা, এটি বজায় রাখতে আরও বেশি সময় ব্যয় করা ইত্যাদি ইত্যাদি)

আপনি এখনই ফাইনালাইজারে কী করতে চান তা বিবেচনা করুন। হয় এটি প্রয়োজনীয়। সেক্ষেত্রে আপনি এটিকে চূড়ান্তকরণে রাখতে পারবেন না, কারণ এটি আপনাকে ডেকে আনা হবে কিনা তা আপনি জানেন না। এটা যথেষ্ট ভাল না। বা এটি প্রয়োজনীয় নয় - তবে আপনি এটি প্রথম স্থানে লেখা উচিত নয়! যেভাবেই হোক, চূড়ান্ত পর্বে এটি রাখা ভুল পছন্দ।

(নোট যে উদাহরণ আপনি নাম, ফাইল স্ট্রিম, ক্লোজিং মত বর্ণন যদি তারা সত্যিই প্রয়োজন হয় না, কিন্তু তারা হিসাবে। এটা ঠিক না যে পর্যন্ত আপনি আপনার সিস্টেমে খোলা ফাইল হ্যান্ডলগুলি সীমা আঘাত, আপনি হবে নোটিশ আপনার কোডটি ভুল। কিন্তু যে সীমা অপারেটিং সিস্টেমের একটি বৈশিষ্ট্য এবং, এমনকি finalizers জন্য জেভিএম নীতির চেয়ে বেশি অনিশ্চিত তাই হয়, তাই এটি সত্যিই সত্যিই হয় গুরুত্বপূর্ণ ফাইল হ্যান্ডলগুলি নষ্ট করবেন না যে।)


যদি আমি কেবল "প্রয়োজনীয়" কোডটি লেখার কথা মনে করি তবে আমার সমস্ত জিইউআই অ্যাপ্লিকেশনগুলিতে সমস্ত স্টাইলিং এড়ানো উচিত? অবশ্যই এর কোনটিই প্রয়োজনীয় নয়; জিইউআইগুলি স্টাইলিং না করে ঠিকঠাক কাজ করবে, এগুলি কেবল ভয়াবহ দেখাচ্ছে। চূড়ান্তকরণকারী সম্পর্কে, কিছু করা প্রয়োজন হতে পারে তবে এটি চূড়ান্তরূপে স্থাপন করা ঠিক আছে, কারণ চূড়ান্তকরণকারীটি বস্তু জিসির সময় বলা হবে, যদি তা না হয়। আপনার যদি কোনও উত্স বন্ধ করতে হয়, বিশেষত যখন এটি আবর্জনা সংগ্রহের জন্য প্রস্তুত থাকে, তবে একটি ফাইনালাইজারটি সর্বোত্তম। হয় প্রোগ্রামটি আপনার সংস্থান প্রকাশের অবসান ঘটায় অথবা চূড়ান্তকরণকারীকে ডাকা হয়।
ক্রু

আমার যদি র‍্যাম ভারী, ব্যয়বহুল থেকে তৈরি, ঘনিষ্ঠযোগ্য অবজেক্ট থাকে এবং আমি এটিকে দুর্বলভাবে উল্লেখ করার সিদ্ধান্ত নিয়েছি, যাতে এটির প্রয়োজন না হলে সাফ হতে পারে, তবে finalize()যদি কোনও জিসি চক্র সত্যিই মুক্ত হওয়ার প্রয়োজন হয় তবে আমি এটিকে বন্ধ করতে ব্যবহার করতে পারি র্যাম. অন্যথায়, আমি যখনই এটি ব্যবহারের প্রয়োজন হয় তখন আমি এটি পুনরায় উত্সাহিত না করে এবং পুনরায় তৈরি করার পরিবর্তে বস্তুটি র‍্যামে রাখি। নিশ্চিতভাবেই, এটি উন্মুক্ত সংস্থানগুলি অবজেক্টটি জিসিইড না হওয়া পর্যন্ত মুক্ত করা হবে না, যখনই তা হতে পারে তবে আমার গ্যারান্টি দেওয়ার প্রয়োজন হতে পারে না যে আমার সংস্থানগুলি একটি নির্দিষ্ট সময়ে মুক্তি দেওয়া হবে।
ক্রু

8

ফাইনালাইজারদের উপর নির্ভর না করার অন্যতম বড় কারণ হ'ল ফাইনালাইজারে পরিষ্কার করার লোভী হতে পারে এমন বেশিরভাগ সংস্থান খুব সীমিত। আবর্জনা সংগ্রহকারী কেবল প্রতি প্রায়শই চালায় কারণ যে কোনও কিছু ছেড়ে দেওয়া যায় কিনা তা নির্ধারণের জন্য রেফারেন্সগুলি অনুসরণ করা ব্যয়বহুল। এর অর্থ হ'ল আপনার বস্তুগুলি আসলে ধ্বংস হওয়ার আগে এটি 'কিছুটা সময়' হতে পারে। আপনার যদি স্বল্প-কালীন ডাটাবেস সংযোগ খোলার প্রচুর অবজেক্ট থাকে, উদাহরণস্বরূপ, এই সংযোগগুলি পরিষ্কার করার জন্য ফাইনালাইজারগুলি ছেড়ে দেওয়া আপনার সংযোগ পুলটি অবসন্ন করতে পারে যখন এটি আবর্জনা সংগ্রাহকের অবশেষে চালিত হয়ে শেষ সংযোগগুলি মুক্ত করার জন্য অপেক্ষা করে। তারপরে, অপেক্ষার কারণে, আপনি সারিবদ্ধ অনুরোধগুলির একটি বৃহত ব্যাকলগ দিয়ে সরিয়ে ফেলেন যা দ্রুত সংযোগ পুলটি আবার নিঃশেষ করে দেয়। এটা '

অতিরিক্তভাবে, চেষ্টা-সহ-সংস্থানগুলির ব্যবহার সমাপ্তিতে 'ক্লোজেবল' অবজেক্টগুলিকে করা সহজ করে তোলে। আপনি যদি এই নির্মাণের সাথে পরিচিত না হন তবে আমি আপনাকে এটি পরীক্ষা করে দেখার পরামর্শ দিই: https://docs.oracle.com/javase/tutorial/essential/exception/tryResourceClose.html


8

চূড়ান্তকরণের কেন এটি সম্পদ প্রকাশের জন্য ছেড়ে দেওয়া সাধারণত একটি খারাপ ধারণা, চূড়ান্তকরণযোগ্য বস্তুগুলি কার্য সম্পাদনের উপর দিয়ে আসে with

থেকে জাভা তত্ত্ব ও অনুশীলন: বর্জ্য সংগ্রহ ও কর্মক্ষমতা (ব্রায়ান Goetz), Finalizers আপনার বন্ধু নও :

চূড়ান্তকরণকারী (যেগুলির মধ্যে একটি তুচ্ছ-চূড়ান্ত চূড়ান্তকরণ পদ্ধতি) রয়েছে তাদের অবজেক্টগুলির চূড়ান্তকরণ ছাড়াই থাকা সামগ্রীর তুলনায় উল্লেখযোগ্য ওভারহেড থাকে এবং অল্প ব্যবহার করা উচিত। চূড়ান্তকরণযোগ্য অবজেক্টগুলি বরাদ্দ করা ধীর এবং সংগ্রহের জন্য ধীর। বরাদ্দের সময়, জেভিএম অবশ্যই আবর্জনা সংগ্রাহকের সাথে যে কোনও চূড়ান্ত করতে সক্ষম বস্তু নিবন্ধ করতে হবে এবং (অন্তত হটস্পট জেভিএম বাস্তবায়নে) চূড়ান্ত করতে সক্ষম অবজেক্টগুলিকে অবশ্যই অন্যান্য অবজেক্টের তুলনায় ধীর বরাদ্দ পাথ অনুসরণ করতে হবে। একইভাবে, চূড়ান্তকরণযোগ্য অবজেক্টগুলি সংগ্রহ করাও ধীর। চূড়ান্তকরণযোগ্য বস্তুর পুনঃনির্মাণের আগে কমপক্ষে দুটি আবর্জনা সংগ্রহের চক্র লাগে (সর্বোত্তম ক্ষেত্রে) এবং চূড়ান্তকরণকারীকে ডাকতে আবর্জনা সংগ্রহকারীকে অতিরিক্ত কাজ করতে হয়। ফলাফলটি বরাদ্দকরণ এবং অবজেক্টগুলি সংগ্রহ করা এবং আবর্জনা সংগ্রাহকের উপর আরও চাপ বেশি সময় ব্যয় করে, অ্যাক্সেসযোগ্য চূড়ান্তকরণযোগ্য বস্তুর দ্বারা ব্যবহৃত মেমরিটি বেশি দিন ধরে রাখা যায়। ফাইনালাইজারদের কোনও ভবিষ্যদ্বাণীমূলক সময়সীমার, বা এমনকি আদৌ চালানোর গ্যারান্টি দেওয়া হয় না এর সাথে একত্রিত হন এবং আপনি দেখতে পারেন যে অপেক্ষাকৃত কয়েকটি পরিস্থিতি রয়েছে যার জন্য চূড়ান্তকরণটি সঠিকভাবে ব্যবহার করার উপযুক্ত সরঞ্জাম।


দুর্দান্ত পয়েন্ট। আমার উত্তরটি দেখুন যা ওভারহেডের কর্মক্ষমতা এড়ানো একটি উপায় সরবরাহ করে finalize()
মাইক নাকিস

7

আমার (কমপক্ষে) এড়ানোর প্রিয় কারণটি Object.finalizeএটি নয় যে আপনি প্রত্যাশার পরে অবজেক্টগুলি চূড়ান্ত হতে পারে, তবে আপনি এটি প্রত্যাশা করার আগে সেগুলি চূড়ান্ত করা যেতে পারে। সমস্যাটি এমন নয় যে জাভা স্থিতিপ্রাপ্ত হওয়ার আগে জাভাটি আর অ্যাক্সেসযোগ্য নয় is

void test() {
   HasFinalize myObject = ...;
   OutputStream os = myObject.stream;

   // myObject is no-longer reachable at this point, 
   // even though it is in scope. But objects are finalized
   // based on reachability.
   // And since finalization is on another thread, it 
   // could happen before or in the middle of the write .. 
   // closing the stream and causing much fun.
   os.write("Hello World");
}

আরও তথ্যের জন্য এই প্রশ্নটি দেখুন । আরও মজার বিষয় হ'ল এই সিদ্ধান্তটি কেবলমাত্র হট স্পট অপ্টিমাইজেশন কিকের পরে নেওয়া হবে, এটি ডিবাগ করার জন্য বেদনাদায়ক করে তোলে।


1
জিনিসটি হ'ল HasFinalize.streamনিজেই একটি পৃথক চূড়ান্তযোগ্য বস্তু হওয়া উচিত। অর্থাৎ চূড়ান্তকরণের HasFinalizeচূড়ান্তকরণ বা পরিষ্কার-পরিচ্ছন্নতার চেষ্টা করা উচিত নয় stream। বা যদি এটি করা উচিত, তবে এটি streamঅ্যাক্সেসযোগ্য করা উচিত ।
নিখুঁত


4

কোনও বস্তুর নিকটে () প্রয়োগকরণ রয়েছে কিনা তা আমাকে নিয়মিত পরীক্ষা করে দেখতে হবে এবং আমি নিশ্চিত যে অতীতে কিছু পয়েন্টে আমি এর কয়েকটি কল মিস করেছি।

Eclipse এ, যখনই আমি প্রয়োগ Closeable/ / প্রয়োগ করে এমন কিছু বন্ধ করতে ভুলে যাই তখনই আমি একটি সতর্কতা পাই AutoCloseable। আমি নিশ্চিত নই যে এটি কোনও গ্রহগ্রহের জিনিস বা এটি সরকারী সংকলকের অংশ কিনা তবে সেখানে আপনাকে সহায়তা করতে আপনি অনুরূপ স্থির বিশ্লেষণ সরঞ্জাম ব্যবহার করতে পারেন। উদাহরণস্বরূপ, ফাইন্ডব্যাগগুলি সম্ভবত আপনি কোনও সংস্থান বন্ধ করতে ভুলে গেছেন কিনা তা যাচাই করতে আপনাকে সহায়তা করতে পারে।


1
ভাল ধারণা উল্লেখ AutoCloseable। এটি এন্টার-রিসোর্স-এর সাহায্যে রিসোর্সগুলি পরিচালনা করতে মস্তিষ্ক-মৃত-সহজ করে তোলে। এটি প্রশ্নের বেশ কয়েকটি যুক্তি বাতিল করে দেয়।

2

আপনার প্রথম প্রশ্ন:

কোনও বস্তুর অবনতি করার সঠিক সময় কখন বিকাশকারী নয়, তা নির্ধারণ করা ভিএম বাস্তবায়ন এবং জিসির উপর নির্ভর করে। কখন Object.finalize()ডাকা হবে তা সিদ্ধান্ত নেওয়া কেন জরুরি ?

ঠিক আছে, জেভিএম নির্ধারণ করবে, যখন কোনও সামগ্রীর জন্য বরাদ্দকৃত স্টোরেজটি পুনরায় দাবি করার জন্য এটি ভাল পয়েন্ট is রিসোর্সটি পরিষ্কার হওয়ার সময় এটি প্রয়োজন হয় না, আপনি সম্পাদন করতে চানfinalize() হওয়া উচিত নয়। এসও সম্পর্কিত "জাভা 8-তে দৃ reac়রূপে পৌঁছনীয় বস্তুর উপর আহ্বান জানানো" - এ এটি চিত্রিত হয়েছে । সেখানে, কোনও close()পদ্ধতিকে একটি পদ্ধতি দ্বারা ডাকা হয়েছে finalize(), একই স্ট্রিম থেকে স্ট্রিম থেকে পড়ার চেষ্টা এখনও মুলতুবি রয়েছে। সুতরাং finalize()দেরিতে যাওয়ার পথে পরিচিত হওয়ার সম্ভাব্য সম্ভাবনাগুলি ছাড়াও এটি খুব তাড়াতাড়ি কল হওয়ার সম্ভাবনা রয়েছে।

আপনার দ্বিতীয় প্রশ্নের ভিত্তি:

সাধারণত, এবং আমি ভুল হলে আমাকে সংশোধন করুন, Object.finalize()জিসি চালানোর সুযোগ পাওয়ার আগে অ্যাপ্লিকেশনটি বন্ধ হয়ে যাওয়ার একমাত্র সময়টি বলা হত না।

সহজভাবে ভুল। কোনও জেভিএমের চূড়ান্তকরণকে সমর্থন করার কোনও প্রয়োজন নেই। ঠিক আছে, এটি সম্পূর্ণরূপে ভুল নয় কারণ আপনি এখনও এটিকে "চূড়ান্তকরণের আগেই অ্যাপ্লিকেশনটি শেষ হয়ে যায়" বলে ধরে নিয়েছিলেন, আপনার অ্যাপ্লিকেশনটি কখনই বন্ধ হয়ে যাবে বলে ধরে নিয়ে।

তবে আপনার মূল বিবৃতিটির "জিসি" এবং "চূড়ান্তকরণ" শব্দটির মধ্যে ছোট পার্থক্যটি নোট করুন। আবর্জনা সংগ্রহ চূড়ান্তকরণের থেকে পৃথক। একবার মেমোরি ম্যানেজমেন্ট সনাক্ত করে যে কোনও বস্তু অ্যাক্সেসযোগ্য নয়, এটি কেবল তার স্থানটি পুনরায় দাবি করতে পারে, যদি হয় তবে এর কোনও বিশেষত্ব নেইfinalize() পদ্ধতি নেই বা চূড়ান্তকরণ কেবল অসমর্থিত, বা এটি চূড়ান্তকরণের জন্য বস্তুকে সজ্জিত করতে পারে। সুতরাং, কোনও আবর্জনা সংগ্রহের চক্র সম্পূর্ণ হওয়ার অর্থ এই নয় যে চূড়ান্তকরণকারীদের মৃত্যুদন্ড কার্যকর করা হয়। এটি পরবর্তী সময়ে ঘটতে পারে যখন সারি প্রক্রিয়াজাত হয় বা কখনই হয় না।

এই পয়েন্টটি কেন জেভিএমগুলিতে চূড়ান্তকরণ সমর্থন সহ, কেন এটি সংস্থান সাফাইয়ের জন্য নির্ভর করা বিপজ্জনক। আবর্জনা সংগ্রহ মেমরি পরিচালনার একটি অংশ এবং তাই মেমরির প্রয়োজনগুলি দ্বারা ট্রিগার করা। এটি সম্ভব যে আবর্জনা সংগ্রহ কখনই চালিত হয় না কারণ পুরো রানটাইম চলাকালীন পর্যাপ্ত স্মৃতি রয়েছে (ভাল, এটি এখনও "জিসি চালানোর সুযোগ পাওয়ার আগে অ্যাপ্লিকেশনটি সমাপ্ত হয়ে যায়" বিবরণে কোনওভাবে বর্ণনা করে) fits এটিও সম্ভব যে জিসি চালায় তবে পরে যথেষ্ট পরিমাণ মেমরি পুনরুদ্ধার করা যায়, সুতরাং চূড়ান্তকরণকারী সারিটি প্রক্রিয়াজাত হয় না।

অন্য কথায়, এইভাবে পরিচালিত নেটিভ রিসোর্সগুলি মেমরি পরিচালনার জন্য এখনও একটি এলিয়েন। যদিও এটির গ্যারান্টি রয়েছে যে OutOfMemoryErrorমেমরি মুক্ত করার পর্যাপ্ত প্রচেষ্টা করার পরে কেবল একটিটি ফেলে দেওয়া হয়েছে, এটি স্থানীয় উত্স এবং চূড়ান্তকরণের জন্য প্রযোজ্য নয়। চূড়ান্তকরণের সারিটি এই সংস্থানগুলিকে মুক্ত করতে পারে এমন চূড়ান্তকরণের সারিতে থাকা অপ্রতুল সংস্থার কারণে কোনও ফাইল খোলার ব্যর্থতা যদি চূড়ান্তরূপে চালিত হয় ...

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.