জাভাতে আবর্জনা সংগ্রহ করা জোর করে দেওয়া কী সম্ভব, এমনকি যদি তা করাও কৃপণ হয়? আমি জানি System.gc();
এবং Runtime.gc();
তবে তারা কেবল জিসি করার পরামর্শ দেয়। আমি কীভাবে জিসিকে জোর করতে পারি?
জাভাতে আবর্জনা সংগ্রহ করা জোর করে দেওয়া কী সম্ভব, এমনকি যদি তা করাও কৃপণ হয়? আমি জানি System.gc();
এবং Runtime.gc();
তবে তারা কেবল জিসি করার পরামর্শ দেয়। আমি কীভাবে জিসিকে জোর করতে পারি?
উত্তর:
আপনার সর্বোত্তম বিকল্পটি কল করা System.gc()
যা কোনও আবর্জনা সংগ্রহকারীকে কেবল কোনও ইঙ্গিত হিসাবে বলা হয় যে আপনি এটি সংগ্রহ করতে চান। আবর্জনা সংগ্রহকারী অ-নিরস্তক হওয়ায় বাধ্য ও তাত্ক্ষণিকভাবে সংগ্রহের কোনও উপায় নেই ।
non-deterministic == trouble
GC.Collect()
সংগ্রহ করে না। জাভা gc()
হয়।
Jlibs গ্রন্থাগার আবর্জনা সংগ্রহের জন্য একটি ভাল ইউটিলিটি বর্গ হয়েছে । WeakReferences অবজেক্টের সাথে একটি নিফটি সামান্য কৌশল ব্যবহার করে আবর্জনা সংগ্রহকে জোর করতে পারেন ।
জালিবগুলি থেকে রানটাইমUtil.gc () :
/**
* This method guarantees that garbage collection is
* done unlike <code>{@link System#gc()}</code>
*/
public static void gc() {
Object obj = new Object();
WeakReference ref = new WeakReference<Object>(obj);
obj = null;
while(ref.get() != null) {
System.gc();
}
}
PhantomReference
দিয়ে ব্যবহার করা ReferenceQueue
এবং তারপরে আপনাকে চূড়ান্তকরণের পরে অবহিত করা হবে তবে পরিষ্কার করার আগেও। অবশেষে, এমনকি যদি আপনি সফলভাবে সনাক্ত করেছেন যে এই বস্তুর জন্য মেমরিটি পুনরুদ্ধার করা হয়েছে, তবে এটি হটস্পটের মতো প্রজন্মের জিসিতে খুব সামান্যই বোঝায়। সাধারণত এটি তরুণ প্রজন্মের ক্লিনআপের সাথে মিলে যায়।
System.gc(); System.gc();
, তবে এটি এটির চেয়ে আরও ভালভাবে কাজ করে কিনা তা জানতে আগ্রহী হবে। আসলে, কতবার এটি প্রিন্ট করা প্রিন্ট করা System.gc()
যথেষ্ট ছিল। 2 এ পৌঁছানোর সুযোগটি বেশ পাতলা।
জিসিকে জোর করার সর্বোত্তম (কেবলমাত্র না) উপায় হ'ল একটি কাস্টম জেভিএম লেখা। আমি বিশ্বাস করি যে আবর্জনা সংগ্রাহকরা প্লাগযোগ্য হবেন তাই আপনি সম্ভবত উপলভ্য বাস্তবায়নগুলির মধ্যে একটি বেছে নিতে পারেন এবং এটি টুইট করতে পারেন।
দ্রষ্টব্য: এটি কোনও সহজ উত্তর নয়।
ব্যবহার জাভা ™ ভার্চুয়াল মেশিন টুল ইন্টারফেস (জেভিএম টিআই) , ফাংশন
jvmtiError ForceGarbageCollection(jvmtiEnv* env)
"ভিএম কে জঞ্জাল সংগ্রহ করতে বাধ্য করবে" " জেভিএম টিআই জাভাটিএম প্ল্যাটফর্ম ডিবাগার আর্কিটেকচারের (জেপিডিএ) অংশ ।
হ্যাঁ আপনাকে একই পদ্ধতিতে একই সাথে পদ্ধতিতে কল করতে বাধ্য করা প্রায় সম্ভব এবং একই সাথে এইগুলি হ'ল:
System.gc ();
System.runFinalization ();
এমনকি একই সময়ে এই দুটি পদ্ধতির ব্যবহার পরিষ্কার করার জন্য যদি কেবলমাত্র একটি অবজেক্ট থাকে তবে আবর্জনা সংগ্রহকারীকে finalise()
অ্যাক্সেসযোগ্য অবজেক্টের পদ্ধতিটি নির্ধারিত স্মৃতি মুক্ত করে এবং finalize()
পদ্ধতিটি কী বলে তা করতে বাধ্য করে ।
যাইহোক এটি আবর্জনা সংগ্রহকারীকে ব্যবহার করা একটি ভয়ানক অনুশীলন কারণ এটির ব্যবহারের ফলে সফটওয়্যারটিতে একটি অতিরিক্ত বোঝা প্রবর্তিত হতে পারে যা মেমরির চেয়েও খারাপ হতে পারে, আবর্জনা সংগ্রাহকের নিজস্ব থ্রেড রয়েছে যা প্লাসের উপর নির্ভর করে নিয়ন্ত্রণ করা সম্ভব নয় গিসি দ্বারা ব্যবহৃত অ্যালগরিদম আরও সময় নিতে পারে এবং খুব অদক্ষ বিবেচনা করা হয়, আপনার সফ্টওয়্যারটি এটি সিসি এর সাহায্যে সবচেয়ে খারাপ হয় কিনা তা পরীক্ষা করা উচিত কারণ এটি অবশ্যই ভেঙে গেছে, একটি ভাল সমাধান অবশ্যই জিসির উপর নির্ভর করে না।
দ্রষ্টব্য: কেবলমাত্র মাথায় রাখার জন্য এটি কেবল তখনই কাজ করবে যদি চূড়ান্তকরণ পদ্ধতিতে কোনও বস্তুর পুনর্নির্দিষ্টকরণ না হয়, যদি এটি ঘটে তবে বস্তুটি জীবিত থাকবে এবং প্রযুক্তিগতভাবে সম্ভব এটির পুনরুত্থান হবে।
gc()
কেবল আবর্জনা সংগ্রহ চালানোর ইঙ্গিত। runFinalizers()
কেবল "বস্তুগুলিতে চূড়ান্তকরণগুলি চালিত হয় যা" ফেলে দেওয়া হয়েছে "। জিসি যদি প্রকৃতপক্ষে না চালিত হয় তবে এ জাতীয় কোনও জিনিস নাও থাকতে পারে ...
আউটআফমিউরিওরোর ডকুমেন্টেশনের আওতায় এটি ঘোষণা করে যে পূর্ণ আবর্জনা সংগ্রহের পরে ভিএম মেমরিটি পুনরায় দাবি করতে ব্যর্থ না হলে এটি ফেলে দেওয়া হবে না। সুতরাং আপনি ত্রুটি না পাওয়া পর্যন্ত যদি মেমরি বরাদ্দ রাখেন তবে আপনি ইতিমধ্যে একটি সম্পূর্ণ আবর্জনা সংগ্রহ করতে বাধ্য হবেন।
সম্ভবত আপনি যে প্রশ্নটি জিজ্ঞাসা করতে চেয়েছিলেন তা হ'ল "আমি আবর্জনা সংগ্রহের মাধ্যমে আমার যে স্মৃতি পুনরায় দাবি করা উচিত তা কীভাবে দাবি করতে পারি?"
ম্যানুয়ালি জিসিকে অনুরোধ করতে (System.gc () থেকে নয়):
.gc ভবিষ্যতের রিলিজগুলিতে নির্মূলের প্রার্থী - একটি সান ইঞ্জিনিয়ার একবার মন্তব্য করেছিলেন যে বিশ্বের বিশেরও কম লোক আসলে .gc () ব্যবহার করতে জানেন যে - আমি গতরাতে কেন্দ্রীয় / সমালোচনামূলক কয়েক ঘন্টা কিছু কাজ করেছি SecureRandom উত্পন্ন ডেটা ব্যবহার করে ডেটা-স্ট্রাকচার, কোথাও কোথাও মাত্র ৪০,০০০ অবজেক্ট ভিএমএম ধীর হয়ে উঠবে যেন এটি পয়েন্টারের বাইরে চলে গেছে। স্পষ্টতই এটি 16-বিট পয়েন্টার টেবিলগুলিতে ক্লান্ত হয়ে পড়েছিল এবং ক্লাসিক "ব্যর্থ যন্ত্রপাতি" আচরণের প্রদর্শন করেছিল।
আমি এক্সএএমএস এবং আরও চেষ্টা করেছিলাম, যতক্ষণ না এটি প্রায় 57, এক্সএক্সএক্সএক্স কিছু না চালিত হয় ততক্ষণ কিছুটা বার বার ঝাঁকুনি দিয়েছিল। তারপরে এটি ক্যাম্প ইজি মানি-তে কোড-ব্লাটের গতি সম্পর্কে - একটি সিসি () এর পরে 57,127 থেকে 57,128 বলার পরে এটি জিসি চালিত হবে।
আপনার ডিজাইনের মৌলিক পুনরায় কাজ দরকার, সম্ভবত একটি স্লাইডিং উইন্ডো পদ্ধতির।
আপনি কমান্ড লাইন থেকে একটি জিসি ট্রিগার করতে পারেন। এটি ব্যাচ / ক্রন্টাবের জন্য দরকারী:
jdk1.7.0/bin/jcmd <pid> GC.run
দেখা :
জেভিএম স্পেসিফিকেশন আবর্জনা সংগ্রহের বিষয়ে নির্দিষ্ট কিছু বলে না। এ কারণে বিক্রেতারা তাদের পথে জিসি বাস্তবায়নে নিখরচায় রয়েছেন।
সুতরাং এই অস্পষ্টতা আবর্জনা সংগ্রহের আচরণে অনিশ্চয়তার কারণ ঘটায়। আবর্জনা সংগ্রহের পদ্ধতির / অ্যালগরিদমগুলি সম্পর্কে জানতে আপনার জেভিএমের বিশদটি পরীক্ষা করা উচিত। এছাড়াও আচরণ কাস্টমাইজ করার বিকল্প আছে।
আপনার যদি জঞ্জাল সংগ্রহের জন্য জোর করতে হয় তবে সম্ভবত আপনি কীভাবে সংস্থানগুলি পরিচালনা করছেন তা বিবেচনা করা উচিত। আপনি কি স্মৃতিতে অবিচল থাকা বড় বড় অবজেক্ট তৈরি করছেন? আপনি কি এমন বড় বড় অবজেক্ট (যেমন গ্রাফিক্স ক্লাস) তৈরি করছেন যা একটি Disposable
ইন্টারফেস রয়েছে এবং dispose()
এটি সম্পন্ন করার পরে কল করছে না? আপনি কি ক্লাস স্তরে এমন কিছু ঘোষণা করছেন যা কেবলমাত্র একটি পদ্ধতিতে আপনার প্রয়োজন?
আপনার আবর্জনা সংগ্রহের প্রয়োজনীয়তার কারণটি যদি আপনি বর্ণনা করেন তবে ভাল হয়। আপনি যদি এসডব্লিউটি ব্যবহার করেন তবে আপনি যেমন Image
এবং Font
ফ্রি মেমরির মতো সংস্থানগুলি নিষ্পত্তি করতে পারেন । এই ক্ষেত্রে:
Image img = new Image(Display.getDefault(), 16, 16);
img.dispose();
অপ্রয়োজনীয় সংস্থান নির্ধারণের জন্য সরঞ্জামগুলিও রয়েছে।
আপনি যদি স্মৃতিশক্তি হারিয়ে ফেলেছেন এবং একটি পেয়ে যাচ্ছেন তবে আপনি OutOfMemoryException
জাভাতে উপলব্ধ হ্যাপ স্পেসের পরিমাণ বাড়ানোর চেষ্টা করতে পারেন java -Xms128m -Xmx512m
ঠিক আপনার পরিবর্তে প্রোগ্রাম শুরু করে java
। এটি আপনাকে প্রাথমিক স্তরের আকার 128Mb এবং সর্বোচ্চ 512Mb দেবে, যা মান 32Mb / 128Mb এর চেয়ে অনেক বেশি।
java -Xms512M -Xmx1024M
অন্য বিকল্প হ'ল নতুন অবজেক্ট তৈরি না করা।
জাভাতে প্রয়োজনীয় জিসি হ্রাস করতে অবজেক্ট পুলিং দূরে।
অবজেক্ট পুলিং সাধারণত অবজেক্ট তৈরির চেয়ে দ্রুততর হয় না (লাইটওয়েট অবজেক্টের জন্য উদাহরণ) তবে এটি আবর্জনা সংগ্রহের চেয়ে দ্রুত is আপনি যদি 10,000 টি বস্তু তৈরি করেন এবং প্রতিটি বস্তু 16 বাইট ছিল। এটি 160,000 বাইট জিসিকে পুনরায় দাবি করতে হবে। অন্যদিকে, আপনার যদি একই সময়ে সমস্ত 10,000 এর প্রয়োজন না হয় তবে আপনি পুনরায় ব্যবহার করতে বা পুনরায় ব্যবহারের জন্য একটি পুল তৈরি করতে পারেন যা নতুন অবজেক্টগুলি নির্মাণের প্রয়োজনীয়তা এবং GC পুরানো অবজেক্টগুলির প্রয়োজনীয়তা দূর করে।
এরকম কিছু (অরক্ষিত)। এবং যদি আপনি এটি থ্রেড নিরাপদ হতে চান তবে আপনি একটি সমকালীন লিঙ্কযুক্ত কিউয়ের জন্য লিংকডলিস্টটি সরিয়ে নিতে পারেন।
public abstract class Pool<T> {
private int mApproximateSize;
private LinkedList<T> mPool = new LinkedList<>();
public Pool(int approximateSize) {
mApproximateSize = approximateSize;
}
public T attain() {
T item = mPool.poll();
if (item == null) {
item = newInstance();
}
return item;
}
public void release(T item) {
int approxSize = mPool.size(); // not guaranteed accurate
if (approxSize < mApproximateSize) {
recycle(item);
mPool.add(item);
} else if (approxSize > mApproximateSize) {
decommission(mPool.poll());
}
}
public abstract T newInstance();
public abstract void recycle(T item);
public void decommission(T item) { }
}
G1 GC এর সাথে ওরাকলজেডিকে 10-তে, একটি একক কল জিসিকে System.gc()
পুরানো সংগ্রহটি পরিষ্কার করার কারণ করবে। আমি নিশ্চিত না যে জিসি তাত্ক্ষণিকভাবে চালায় কিনা। যাইহোক, System.gc()
লুপে বহুবার ফোন করা হলেও জিসি ইয়ং কালেকশনটি পরিষ্কার করবেন না । ইয়ং কালেকশনটি পরিষ্কার করার জন্য জিসি পেতে, আপনাকে new byte[1024]
কল না করে একটি লুপে (যেমন ) বরাদ্দ করতে হবে System.gc()
। System.gc()
কোনও কারণে কল করা জিসিকে তরুণ সংগ্রহ পরিষ্কার করতে বাধা দেয়।
সত্যি, আমি আপনাকে পাই না। তবে "অসীম অবজেক্ট ক্রিয়েশন" সম্পর্কে পরিষ্কার হওয়ার অর্থ আমি বলতে চাইছিলাম যে আমার বড় সিস্টেমে এমন কিছু কোড রয়েছে যা অবজেক্টগুলি তৈরি করে যা মেমোরিতে পরিচালনা করে এবং আমি এই কোডটির টুকরোটি আসলে পেতে পারি না, কেবল অঙ্গভঙ্গি !!
এটি সঠিক, কেবল অঙ্গভঙ্গি। বেশ কয়েকটি পোস্টার ইতিমধ্যে আপনার কাছে দেওয়া বেশ কয়েকটি মানসম্মত উত্তর রয়েছে। একে একে নেওয়া যাক:
ঠিক আছে, কোন আসল জেভিএম নেই - এটি কেবল একটি স্পেসিফিকেশন, একটি কম্পিউটার বিজ্ঞানের একটি গুচ্ছ পছন্দসই আচরণের বর্ণনা দেয় ... আমি সম্প্রতি দেশীয় কোড থেকে জাভা অবজেক্টগুলিকে আরম্ভ করার জন্য খনন করেছি। আপনি যা চান তা পাওয়ার জন্য একমাত্র উপায় হ'ল আক্রমণাত্মক নালিং বলা হয় do ভুল হলে ভুলগুলি এত খারাপ যে আমাদের নিজেদেরকে প্রশ্নের মূল ক্ষেত্রের মধ্যে সীমাবদ্ধ করতে হবে:
এখানে বেশিরভাগ পোস্টার ধরেই নেবে যে আপনি বলছেন যে আপনি কোনও ইন্টারফেসে কাজ করছেন, যদি এরকম হয় তবে আমাদের যদি দেখতে হবে যে আপনাকে একবারে পুরো অবজেক্ট বা একটি আইটেম হস্তান্তর করা হচ্ছে কিনা।
আপনার যদি আর কোনও জিনিসের প্রয়োজন হয় না, আপনি বস্তুকে নাল বরাদ্দ করতে পারেন তবে আপনি যদি এটি ভুল হয়ে থাকেন তবে একটি নাল পয়েন্টার ব্যতিক্রম উত্পন্ন হয়। আমি বাজি ধরছি আপনি যদি এনআইও ব্যবহার করেন তবে আপনি আরও ভাল কাজ করতে পারবেন
আপনি বা আমি বা অন্য কেউ যে কোনও সময় পেলে: " দয়া করে আমার এটি ভয়াবহভাবে দরকার " "আপনি কী কাজ করার চেষ্টা করছেন তা সম্পূর্ণ ধ্বংসের কাছে এটি প্রায় সর্বজনীন পূর্বসূরী .... আমাদের একটি ছোট্ট নমুনা কোড লিখুন, এটি থেকে কোনওরকম স্যানিটাইজিং করে না প্রকৃত কোড ব্যবহৃত হয়েছে এবং আপনার প্রশ্ন আমাদের দেখান।
হতাশ হবেন না। প্রায়শই এটির সমাধান যা আপনার ডিবিএ হ'ল কোথাও কেনা প্যাকেজ ব্যবহার করছে এবং প্রচুর ডেটা স্ট্রাকচারের জন্য মূল নকশাটি টুইট করা হয় না।
এটি খুব সাধারণ বিষয়।
অবগতির জন্য
সিস্টেম কল.সুনফাইনালাইজারসনেক্সট (সত্য) কলটি গ্যারান্টি দেয় যে জাভা বন্ধ হওয়ার আগে চূড়ান্তকরণ পদ্ধতিগুলি বলা হয়। তবে এই পদ্ধতিটি সহজাতভাবে অনিরাপদ এবং হ্রাস করা হয়েছে ated একটি বিকল্প হ'ল রানটাইম.এডিডিশুটডাউনহুক পদ্ধতিটির সাথে "শাটডাউন হুকস" যুক্ত করা।
মাসাররাত সিদ্দিকী
জঞ্জাল সংগ্রহকারীকে বাধ্য করার জন্য কিছু অপ্রত্যক্ষ উপায় রয়েছে। আবর্জনা সংগ্রহকারী কখন কার্যকর হবে সেই বিন্দু না হওয়া পর্যন্ত আপনাকে অস্থায়ী বস্তুগুলির সাথে গাদা পূরণ করতে হবে। আমি এমন ক্লাস তৈরি করেছি যা এইভাবে আবর্জনা সংগ্রহকারীকে বাধ্য করে:
class GarbageCollectorManager {
private static boolean collectionWasForced;
private static int refCounter = 0;
public GarbageCollectorManager() {
refCounter++;
}
@Override
protected void finalize() {
try {
collectionWasForced = true;
refCounter--;
super.finalize();
} catch (Throwable ex) {
Logger.getLogger(GarbageCollectorManager.class.getName()).log(Level.SEVERE, null, ex);
}
}
public int forceGarbageCollection() {
final int TEMPORARY_ARRAY_SIZE_FOR_GC = 200_000;
int iterationsUntilCollected = 0;
collectionWasForced = false;
if (refCounter < 2)
new GarbageCollectorManager();
while (!collectionWasForced) {
iterationsUntilCollected++;
int[] arr = new int[TEMPORARY_ARRAY_SIZE_FOR_GC];
arr = null;
}
return iterationsUntilCollected;
}
}
ব্যবহার:
GarbageCollectorManager manager = new GarbageCollectorManager();
int iterationsUntilGcExecuted = manager.forceGarbageCollection();
এই পদ্ধতিটি কতটা দরকারী তা আমি জানি না, কারণ এটি অবিচ্ছিন্নভাবে স্তূপগুলি পূরণ করে, তবে আপনার যদি মিশন সমালোচনামূলক অ্যাপ্লিকেশন থাকে যা জিসিকে জোর করে বাধ্যতামূলক করে - এটি যখন জিসিকে জোর করার জাভা বহনযোগ্য উপায় হতে পারে।
আমি এখানে কিছু যুক্ত করতে চাই। অনুগ্রহ করে জাভা ভার্চুয়াল মেশিনে চালিত হয় এবং প্রকৃত মেশিনে নয়। ভার্চুয়াল মেশিনটির মেশিনটির সাথে যোগাযোগের নিজস্ব নিজস্ব পদ্ধতি রয়েছে। এটি সিস্টেম থেকে সিস্টেমে পরিবর্তিত হতে পারে। এখন আমরা যখন জিসিকে কল করি তখন আমরা জাভার ভার্চুয়াল মেশিনকে আবর্জনা সংগ্রাহককে কল করতে বলি।
যেহেতু আবর্জনা সংগ্রাহক ভার্চুয়াল মেশিনের সাথে রয়েছে, তাই আমরা এটির পরে সেখানে কোনও ক্লিনআপ করতে বাধ্য করতে পারি না। বরং আমরা আবর্জনা সংগ্রাহকের সাথে আমাদের অনুরোধটি সারি করি। এটি ভার্চুয়াল মেশিনের উপর নির্ভর করে, নির্দিষ্ট সময়ের পরে (এটি সিস্টেম থেকে সিস্টেমে পরিবর্তিত হতে পারে, সাধারণত যখন জেভিএমকে বরাদ্দ করা প্রান্তিক মেমরি পূর্ণ থাকে) আসল মেশিনটি স্থানটি খালি করে দেয়। : ডি
নিম্নলিখিত কোডটি assertGC (...) পদ্ধতি থেকে নেওয়া হয়েছে। এটি নিরপেক্ষতাবাদী আবর্জনা সংগ্রহকারীকে সংগ্রহ করতে বাধ্য করার চেষ্টা করে।
List<byte[]> alloc = new ArrayList<byte[]>();
int size = 100000;
for (int i = 0; i < 50; i++) {
if (ref.get() == null) {
// Test succeeded! Week referenced object has been cleared by gc.
return;
}
try {
System.gc();
} catch (OutOfMemoryError error) {
// OK
}
try {
System.runFinalization();
} catch (OutOfMemoryError error) {
// OK
}
// Approach the jvm maximal allocatable memory threshold
try {
// Allocates memory.
alloc.add(new byte[size]);
// The amount of allocated memory is increased for the next iteration.
size = (int)(((double)size) * 1.3);
} catch (OutOfMemoryError error) {
// The amount of allocated memory is decreased for the next iteration.
size = size / 2;
}
try {
if (i % 3 == 0) Thread.sleep(321);
} catch (InterruptedException t) {
// ignore
}
}
// Test failed!
// Free resources required for testing
alloc = null;
// Try to find out who holds the reference.
String str = null;
try {
str = findRefsFromRoot(ref.get(), rootsHint);
} catch (Exception e) {
throw new AssertionFailedErrorException(e);
} catch (OutOfMemoryError err) {
// OK
}
fail(text + ":\n" + str);
উত্স (আমি স্বচ্ছতার জন্য কিছু মন্তব্য যুক্ত করেছি): NbTestCase উদাহরণ
আপনি Runtime.getRuntime().gc()
ইউটিলিটি পদ্ধতিটি ব্যবহার বা ব্যবহারের চেষ্টা করতে পারেন System.gc()
দ্রষ্টব্য: এই পদ্ধতিগুলি জিসি নিশ্চিত করে না। এবং তাদের ক্ষেত্রটি আপনার অ্যাপ্লিকেশনটিতে প্রোগ্রামগতভাবে পরিচালনা করার চেয়ে জেভিএমের মধ্যে সীমাবদ্ধ হওয়া উচিত।