আমি কি জ্যাকসনের অবজেক্টম্যাপারকে স্থির ক্ষেত্র হিসাবে ঘোষণা করব?


361

জ্যাকসন লাইব্রেরির ObjectMapperক্লাসটি থ্রেড নিরাপদ বলে মনে হচ্ছে

এর অর্থ কি এই যে আমার ObjectMapperএইরকম স্থিতিশীল ক্ষেত্র হিসাবে ঘোষনা করা উচিত

class Me {
    private static final ObjectMapper mapper = new ObjectMapper();
}

পরিবর্তে এই যেমন একটি উদাহরণ স্তরের ক্ষেত্র হিসাবে?

class Me {
    private final ObjectMapper mapper = new ObjectMapper();
}

উত্তর:


505

হ্যাঁ, এটি নিরাপদ এবং প্রস্তাবিত।

আপনি উল্লেখ করা পৃষ্ঠার একমাত্র সতর্কতা হ'ল ম্যাপারটি ভাগ হয়ে গেলে আপনি কনফিগারেশনটি পরিবর্তন করতে পারবেন না; তবে আপনি কনফিগারেশন পরিবর্তন করছেন না তাই ঠিক আছে। আপনার যদি কনফিগারেশন পরিবর্তন করার দরকার পড়ে, আপনি এটি স্ট্যাটিক ব্লক থেকে করবেন এবং এটি ভালও হবে।

সম্পাদনা : (2013-10)

২.০ এবং তার উপরে, উপরে আরও উন্নততর উপায় রয়েছে তা উল্লেখ করে বাড়ানো যেতে পারে: ব্যবহার ObjectWriterএবং ObjectReaderঅবজেক্ট, যা দ্বারা নির্মিত হতে পারে ObjectMapper। এগুলি সম্পূর্ণরূপে অপরিবর্তনীয়, থ্রেড-নিরাপদ, যার অর্থ থ্রেড-সুরক্ষা সমস্যাগুলি উত্পন্ন করা তাত্ত্বিকভাবেও সম্ভব নয় ( ObjectMapperকোডটি পুনরায় কনফিগার করার চেষ্টা করলে কোডটি ঘটতে পারে )।


23
@ স্ট্যাকসম্যান: ডাকা ObjectMapperহওয়ার পরেও যদি থ্রেড-সেফ থাকে তবে আমি কিছুটা উদ্বিগ্ন ObjectMapper#setDateFormat()। এটি জানা যায় যে SimpleDateFormatথ্রেড নিরাপদ নয় , সুতরাং এটি ObjectMapperযদি না হয় তবে এটি SerializationConfigপ্রতিটির আগে ক্লোন না করে writeValue()(আমি সন্দেহ করি)। তুমি কি আমার ভয় ডেকে দিতে পার?
dma_k

49
DateFormatপ্রকৃতপক্ষে ফণা অধীন ক্লোন করা হয়। ভাল সন্দেহ আছে, কিন্তু আপনি আবৃত। :)
স্টেক্সম্যান

3
একটি বৃহত এন্টারপ্রাইজ অ্যাপ্লিকেশনটির ইউনিট / সংহতকরণ পরীক্ষার সময় আমি অদ্ভুত আচরণের মুখোমুখি হয়েছি। স্থিতিশীল চূড়ান্ত শ্রেণীর বৈশিষ্ট্য হিসাবে অবজেক্টম্যাপার স্থাপন করার সময় আমি পার্মজেন সমস্যাগুলির মুখোমুখি হতে শুরু করি। কেউ কি সম্ভাব্য কারণগুলি ব্যাখ্যা করার যত্ন নেবেন? আমি জ্যাকসন-ডেটাবাইন্ড সংস্করণটি ২.৪.১ ব্যবহার করছিলাম।
আলেজো সেবাল্লো

2
@ মিক্লোসক্রিভান আপনি কি আদৌ তাকিয়েছেন ObjectMapper?! পদ্ধতির নাম দেওয়া হয়েছে writer()এবং reader()(এবং কিছু readerFor(), writerFor())।
স্ট্যাক্সম্যান

2
কোনও mapper.with()কল নেই (যেহেতু জ্যাকসনের "উইথ" একটি নতুন উদাহরণ নির্মাণ, এবং থ্রেড-সেফ এক্সিকিউশনকে বোঝায়)। তবে কনফিগার পরিবর্তনগুলি সম্পর্কিত: কোনও চেকিং করা হয়নি, সুতরাং কনফিগার অ্যাক্সেস ObjectMapperঅবশ্যই রক্ষা করা উচিত। "অনুলিপি ()" হিসাবে: হ্যাঁ, এটি একটি নতুন নতুন অনুলিপি তৈরি করে যা একই নিয়ম অনুসারে পুরোপুরি (পুনরায়) কনফিগার করা যেতে পারে: প্রথমে এটি সম্পূর্ণরূপে কনফিগার করুন, তারপরে ব্যবহার করুন এবং এটি ঠিক আছে। অ-তুচ্ছ ব্যয় যুক্ত আছে (যেহেতু অনুলিপি ক্যাশেড হ্যান্ডলারগুলির কোনওটিই ব্যবহার করতে পারে না) তবে এটি নিরাপদ উপায়, হ্যাঁ।
স্টেক্সম্যান

53

যদিও অবজেক্টম্যাপার থ্রেড নিরাপদ, তবুও আমি এটিকে একটি স্ট্যাটিক ভেরিয়েবল হিসাবে বিশেষত মাল্টিথ্রেডেড অ্যাপ্লিকেশন হিসাবে ঘোষণা করা থেকে নিরুৎসাহিত করব। এটি একটি খারাপ অনুশীলন বলেও নয়, তবে আপনি ডেডলকিংয়ের একটি ভারী ঝুঁকি নিয়ে চলেছেন। আমি এটি আমার নিজের অভিজ্ঞতা থেকে বলছি। আমি 4 টি অভিন্ন থ্রেড সহ একটি অ্যাপ্লিকেশন তৈরি করেছি যা ওয়েব পরিষেবাদি থেকে জেএসএন ডেটা পাচ্ছে এবং প্রক্রিয়াকরণ করছে। থ্রেড ডাম্প অনুসারে আমার অ্যাপ্লিকেশনটি নিম্নলিখিত কমান্ডটিতে প্রায়শই স্টল করছিল:

Map aPage = mapper.readValue(reader, Map.class);

তার পাশেই পারফরম্যান্স ভাল ছিল না। আমি যখন ইনস্ট্যান্স ভিত্তিক ভেরিয়েবলের সাথে স্থিতিশীল ভেরিয়েবলটি প্রতিস্থাপন করি তখন স্টলিং অদৃশ্য হয়ে গেল এবং পারফরম্যান্স চারগুণ হয়ে গেল। অর্থাত্ 2.4 মিলিয়ন জেএসওএন নথিগুলি 2.5 ঘন্টা পূর্বে পরিবর্তে 40 মিনিট.56 সেকেন্ডে প্রক্রিয়া করা হয়েছিল।


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

এবং অবশ্যই, একটি বজায় রাখা ObjectPool আপনার সাথে যেতে সেরা উপায় - যার মাধ্যমে সেরা GCএবং Lockঅভিনয় দেওয়া nces অ্যাপাচি-কমন এর ObjectPoolপ্রয়োগের জন্য আপনি নীচের লিঙ্কটি উল্লেখ করতে পারেন । commons.apache.org/proper/commons-pool/api-1.6/org/apache/…
অভিদেমন

16
আমি একটি বিকল্প সুপারিশ করবে: স্ট্যাটিক রাখা ObjectMapperকোথাও, কিন্তু শুধুমাত্র পেতে ObjectReader/ ObjectWriterদৃষ্টান্ত (সাহায্যকারী পদ্ধতির মাধ্যমে), অন্যান্য স্থানে যারা রেফারেন্স ধরে রাখা (অথবা পরিবর্তনশীল কল)। এই পাঠক / লেখক অবজেক্টগুলি কেবল পুরোপুরি থ্রেড-নিরাপদ আর্ট পুনর্গঠনই নয়, খুব হালকা ওজনও রয়েছে (আর্ট ম্যাপার উদাহরণগুলি)। তাই হাজার হাজার রেফারেন্স রাখলে বেশি মেমরির ব্যবহার যুক্ত হয় না।
স্টেক্সম্যান

সুতরাং অবজেক্টরিডারের উদাহরণগুলিতে ব্লক করা হচ্ছে না যেমন অবজেক্টরেইডার.ড্রেডট্রি কে মাল্টিথ্রেডেড অ্যাপ্লিকেশনটিতে ডাকা হয়, জ্যাকসন ২.৮.x ব্যবহার করে থ্রেডগুলি অন্য থ্রেডের জন্য অপেক্ষা করা অবরুদ্ধ করা হবে
শেফোনিয়া

1

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

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

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

অবজেক্টম্যাপারের ক্ষেত্রে এটির সূক্ষ্ম, তবে সাধারণভাবে এটি খারাপ অভ্যাস এবং আপনার দীর্ঘকালীন অবজেক্টগুলি পরিচালনা করতে সিঙ্গলটন প্যাটার্ন বা বিপরীতমুখী নিয়ন্ত্রণ ব্যবহার করার কোনও সুবিধা নেই।


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

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

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

1
দেরিতে মন্তব্য করা, কিন্তু অবজেক্টম্যাপার বিশেষত এই ধারণার সাথে একমত নন? এটি প্রকাশ করে readerForএবং writerForযা চাহিদা তৈরি করে ObjectReaderএবং ObjectWriterদৃষ্টান্তগুলি দেয়। সুতরাং আমি বলতে চাই যে ম্যাপারটিকে প্রাথমিক কনফিগারেশনের সাথে স্থির কোথাও রেখেছি, তারপরে পাঠকদের / লেখকদের প্রতি কেস কনফিগার সহ আপনার প্রয়োজন মতো পান?
ক্যারিখন

1

এই পিআর থেকে আমি শিখেছি এমন একটি কৌশল আপনি যদি এটি স্থির চূড়ান্ত পরিবর্তনশীল হিসাবে সংজ্ঞায়িত করতে না চান তবে কিছুটা ওভারহেড সংরক্ষণ করতে চান এবং থ্রেডের গ্যারান্টি রাখতে পারেন।

private static final ThreadLocal<ObjectMapper> om = new ThreadLocal<ObjectMapper>() {
    @Override
    protected ObjectMapper initialValue() {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        return objectMapper;
    }
};

public static ObjectMapper getObjectMapper() {
    return om.get();
}

লেখককে কৃতিত্ব


2
তবে মেমরি ফাঁস হওয়ার ঝুঁকি রয়েছে কারণ উইলের ObjectMapperসাথে থ্রেডটি সংযুক্ত করা হবে যা কোনও পুলের অংশ হতে পারে।
কেনস্টন চোই

@ কেনটেনচোই এএফএইউ'র সমস্যা হওয়া উচিত নয়। থ্রেড আসে এবং যায়, থ্রেড স্থানীয়রা থ্রেড নিয়ে আসে এবং যায়। একসাথে থ্রেডের পরিমাণের উপর নির্ভর করে আপনি মেমরিটি বহন করতে পারেন বা নাও করতে পারেন, তবে আমি "ফুটো" দেখছি না।
ইভান বালাশভ

2
@ ইভানবালাভ, তবে যদি থ্রেডটি তৈরি করা হয় / থেকে / থ্রেড পুলে (যেমন টমকটের মতো পাত্রে) ফিরে আসে তবে তা থেকে যায়। এটি কিছু ক্ষেত্রে পছন্দসই হতে পারে তবে এমন কিছু বিষয় সম্পর্কে আমাদের সচেতন হওয়া দরকার।
কেনস্টন চোই

-1

com.fasterxml.jackson.databind.type.TypeFactory._hashMapSuperInterfaceChain (HierarchicType)

com.fasterxml.jackson.databind.type.TypeFactory._findSuperInterfaceChain(Type, Class)
  com.fasterxml.jackson.databind.type.TypeFactory._findSuperTypeChain(Class, Class)
     com.fasterxml.jackson.databind.type.TypeFactory.findTypeParameters(Class, Class, TypeBindings)
        com.fasterxml.jackson.databind.type.TypeFactory.findTypeParameters(JavaType, Class)
           com.fasterxml.jackson.databind.type.TypeFactory._fromParamType(ParameterizedType, TypeBindings)
              com.fasterxml.jackson.databind.type.TypeFactory._constructType(Type, TypeBindings)
                 com.fasterxml.jackson.databind.type.TypeFactory.constructType(TypeReference)
                    com.fasterxml.jackson.databind.ObjectMapper.convertValue(Object, TypeReference)

ক্লাসে পদ্ধতি _hashMapSuperInterfaceChain com.fasterxml.jackson.databind.type.TypeFactory সিঙ্ক্রোনাইজ করা হয়। আমি উচ্চ লোড এ একই বিষয়ে বিতর্ক দেখছি।

স্ট্যাটিক অবজেক্টম্যাপার এড়ানোর অন্য কারণ হতে পারে


1
সর্বশেষতম সংস্করণগুলি পরীক্ষা করে দেখুন (এবং সম্ভবত আপনি এখানে ব্যবহার করেন এমন সংস্করণ নির্দেশ করে)। রিপোর্ট করা ইস্যুগুলির উপর ভিত্তি করে লকিংয়ের উন্নতি হয়েছে এবং জ্যাকসন ২.7-এর জন্য টাইপ রেজোলিউশন (f.ex) পুরোপুরি নতুন করে লেখা হয়েছিল। যদিও এই ক্ষেত্রে, TypeReferenceব্যবহার করার জন্য কিছুটা ব্যয়বহুল জিনিস: যদি সম্ভব হয় JavaTypeতবে এটি সমাধান করা বেশ কিছুটা প্রক্রিয়াজাতকরণ এড়াতে পারে ( TypeReferenceদুর্ভাগ্যবশত - যে কারণে আমি এখানে খনন করব না তা ক্যাশে করা যায় না), কারণ তারা "সম্পূর্ণরূপে সমাধান করা" (সুপার-টাইপ, জেনেরিক টাইপিং ইত্যাদি)।
স্টেক্সম্যান
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.