"Java DateFormat थ्रेडसेफ़ नहीं है" इससे क्या होता है?


143

जावा DateFormat के बारे में हर कोई सावधानी से सुरक्षित नहीं है और मैं इस अवधारणा को सैद्धांतिक रूप से समझता हूं।

लेकिन मैं कल्पना नहीं कर पा रहा हूं कि इसके कारण हम किन वास्तविक मुद्दों का सामना कर सकते हैं। कहते हैं, मैं एक कक्षा में एक DateFormat क्षेत्र है और एक ही बहु थ्रेडेड वातावरण में वर्ग में अलग-अलग तरीकों से (दिनांक स्वरूपण) में उपयोग किया जाता है।

क्या यह कारण होगा:

  • प्रारूप अपवाद जैसे कोई भी अपवाद
  • डेटा में विसंगति
  • कोई और मुद्दा?

यह भी बताइए कि क्यों।


1
यह वही है जो होता है: stackoverflow.com/questions/14309607/…
caw

अभी 2020 है। मेरे परीक्षणों को चलाने (समानांतर में) पता चला कि एक धागे से एक तारीख लापरवाही से वापस आ जाती है जब दूसरा धागा एक तारीख को प्रारूपित करने की कोशिश कर रहा है। मुझे कुछ हफ़्ते में जांच करने पर निर्भर करता है कि यह क्या निर्भर करता है, जब तक कि एक फॉर्मैटर में नहीं पाया जाता है कि एक कंस्ट्रक्टर एक कैलेंडर को तत्काल बताता है, और कैलेंडर बाद में उस तारीख को ले जाता है जिसे हम प्रारूप में लेते हैं। क्या यह अभी भी उनके सिर में 1990 है? कौन जाने।
व्लाद पैट्रीशेव

जवाबों:


264

चलो इसे आज़माएं।

यहां एक कार्यक्रम है जिसमें कई धागे एक साझा का उपयोग करते हैं SimpleDateFormat

कार्यक्रम :

public static void main(String[] args) throws Exception {

    final DateFormat format = new SimpleDateFormat("yyyyMMdd");

    Callable<Date> task = new Callable<Date>(){
        public Date call() throws Exception {
            return format.parse("20101022");
        }
    };

    //pool with 5 threads
    ExecutorService exec = Executors.newFixedThreadPool(5);
    List<Future<Date>> results = new ArrayList<Future<Date>>();

    //perform 10 date conversions
    for(int i = 0 ; i < 10 ; i++){
        results.add(exec.submit(task));
    }
    exec.shutdown();

    //look at the results
    for(Future<Date> result : results){
        System.out.println(result.get());
    }
}

इसे कुछ बार चलाएं और आप देखेंगे:

अपवाद :

कुछ उदाहरण निम्नलिखित हैं:

1।

Caused by: java.lang.NumberFormatException: For input string: ""
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
    at java.lang.Long.parseLong(Long.java:431)
    at java.lang.Long.parseLong(Long.java:468)
    at java.text.DigitList.getLong(DigitList.java:177)
    at java.text.DecimalFormat.parse(DecimalFormat.java:1298)
    at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1589)

2।

Caused by: java.lang.NumberFormatException: For input string: ".10201E.102014E4"
    at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1224)
    at java.lang.Double.parseDouble(Double.java:510)
    at java.text.DigitList.getDouble(DigitList.java:151)
    at java.text.DecimalFormat.parse(DecimalFormat.java:1303)
    at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1589)

3।

Caused by: java.lang.NumberFormatException: multiple points
    at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1084)
    at java.lang.Double.parseDouble(Double.java:510)
    at java.text.DigitList.getDouble(DigitList.java:151)
    at java.text.DecimalFormat.parse(DecimalFormat.java:1303)
    at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1936)
    at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1312)

गलत परिणाम :

Sat Oct 22 00:00:00 BST 2011
Thu Jan 22 00:00:00 GMT 1970
Fri Oct 22 00:00:00 BST 2010
Fri Oct 22 00:00:00 BST 2010
Fri Oct 22 00:00:00 BST 2010
Thu Oct 22 00:00:00 GMT 1970
Fri Oct 22 00:00:00 BST 2010
Fri Oct 22 00:00:00 BST 2010
Fri Oct 22 00:00:00 BST 2010
Fri Oct 22 00:00:00 BST 2010

सही परिणाम :

Fri Oct 22 00:00:00 BST 2010
Fri Oct 22 00:00:00 BST 2010
Fri Oct 22 00:00:00 BST 2010
Fri Oct 22 00:00:00 BST 2010
Fri Oct 22 00:00:00 BST 2010
Fri Oct 22 00:00:00 BST 2010
Fri Oct 22 00:00:00 BST 2010
Fri Oct 22 00:00:00 BST 2010
Fri Oct 22 00:00:00 BST 2010
Fri Oct 22 00:00:00 BST 2010

एक बहु-थ्रेडेड वातावरण में सुरक्षित रूप से DateFormats का उपयोग करने के लिए एक और दृष्टिकोण ऑब्जेक्ट ThreadLocalको पकड़ने के लिए एक चर का उपयोग करना DateFormatहै, जिसका अर्थ है कि प्रत्येक थ्रेड की अपनी प्रतिलिपि होगी और इसे जारी करने के लिए अन्य थ्रेड्स की प्रतीक्षा करने की आवश्यकता नहीं है। इस तरह से:

public class DateFormatTest {

  private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>(){
    @Override
    protected DateFormat initialValue() {
        return new SimpleDateFormat("yyyyMMdd");
    }
  };

  public Date convert(String source) throws ParseException{
    Date d = df.get().parse(source);
    return d;
  }
}

यहाँ अधिक विवरण के साथ एक अच्छी पोस्ट है


1
मुझे यह उत्तर पसंद है :-)
सुंदरराज गोविंदसामी

मुझे लगता है कि इसका कारण यह है कि डेवलपर्स के लिए इतना निराशाजनक है कि पहली नज़र में, ऐसा लगता है कि यह एक 'कार्यात्मक रूप से उन्मुख' फ़ंक्शन कॉल होना चाहिए। उसी इनपुट के लिए, मैं एक ही आउटपुट की उम्मीद करता हूं (भले ही कई थ्रेड इसे कहते हैं)। मुझे लगता है कि उत्तर जावा के डेवलपर्स के लिए नीचे आता है उस समय FOP के लिए सराहना नहीं है कि उन्होंने मूल तिथि समय तर्क लिखा था। इसलिए अंत में, हम कहते हैं कि "इसका कोई कारण नहीं है कि यह इस तरह से है जैसे कि यह गलत है"।
लीजोर्ट

30

मुझे डेटा भ्रष्टाचार की उम्मीद है - उदाहरण के लिए यदि आप एक ही समय में दो तारीखों को पार्स कर रहे हैं, तो आप एक डेटा को दूसरे से प्रदूषित कर सकते हैं।

यह कल्पना करना आसान है कि यह कैसे हो सकता है: पार्सिंग में अक्सर राज्य की एक निश्चित मात्रा को बनाए रखना शामिल होता है जो आपने अब तक पढ़ा है। यदि दो धागे एक ही अवस्था में दोनों रौंद रहे हैं, तो आपको समस्याएँ होंगी। उदाहरण के लिए, प्रकार के क्षेत्र को DateFormatउजागर करता है , और कोड को देखते हुए , कुछ तरीके कॉल करते हैं और अन्य कॉल करते हैंcalendarCalendarSimpleDateFormatcalendar.set(...)calendar.get(...) । यह स्पष्ट रूप से धागा-सुरक्षित नहीं है।

मैंने थ्रेड-सुरक्षित क्यों नहीं है के सटीक विवरण में नहीं देखा DateFormatहै, लेकिन मेरे लिए यह जानना पर्याप्त है कि यह है तुल्यकालन के बिना असुरक्षित - गैर सुरक्षा का सही शिष्टाचार भी रिलीज के बीच बदल सकता है।

व्यक्तिगत तौर पर मैं से पारसर्स का प्रयोग करेंगे Joda समय के बजाय, के रूप में वे कर रहे हैं धागा सुरक्षित - और Joda समय के साथ शुरू करने के लिए एक बेहतर दिनांक और समय एपीआई है :)


1
+1 jodatime और सोनार इसके उपयोग को लागू करने के लिए: mestachs.wordpress.com/2012/03/17/…
mestachs

18

अगर आप Java 8 का उपयोग कर रहे हैं तो आप उपयोग कर सकते हैं DateTimeFormatter

एक पैटर्न से निर्मित एक फॉर्मेटर को कई बार आवश्यक रूप से उपयोग किया जा सकता है, यह अपरिवर्तनीय है और थ्रेड-सुरक्षित है।

कोड:

LocalDate date = LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String text = date.format(formatter);
System.out.println(text);

आउटपुट:

2017-04-17

10

मोटे तौर पर, कि आपको DateFormatकई थ्रेड्स द्वारा एक्सेस किए गए ऑब्जेक्ट के उदाहरण के रूप में परिभाषित नहीं करना चाहिए , या static

दिनांक प्रारूप सिंक्रनाइज़ नहीं हैं। प्रत्येक थ्रेड के लिए अलग प्रारूप इंस्टेंसेस बनाने की अनुशंसा की जाती है।

इसलिए, यदि आपके Foo.handleBar(..)बजाय कई थ्रेड्स द्वारा एक्सेस किया जाता है, तो इसके बजाय:

public class Foo {
    private DateFormat df = new SimpleDateFormat("dd/mm/yyyy");

    public void handleBar(Bar bar) {
        bar.setFormattedDate(df.format(bar.getStringDate());  
    }
}

आपको उपयोग करना चाहिए:

public class Foo {

    public void handleBar(Bar bar) {
        DateFormat df = new SimpleDateFormat("dd/mm/yyyy");
        bar.setFormattedDate(df.format(bar.getStringDate());  
    }
}

इसके अलावा, सभी मामलों में, एक नहीं है static DateFormat

जैसा कि जॉन स्कीट ने उल्लेख किया है, आपके द्वारा बाह्य तुल्यकालन (यानी synchronizedकॉल के चारों ओर उपयोग DateFormat) के मामले में आपके पास स्थिर और एक साझा उदाहरण चर दोनों हो सकते हैं।


2
मैं यह नहीं देखता कि इस प्रकार है। मैं अपने अधिकांश प्रकारों को थ्रेड-सेफ नहीं बनाता, इसलिए मुझे उम्मीद नहीं है कि उनके उदाहरण वेरिएबल्स थ्रेड-सुरक्षित होंगे। यह कहना अधिक उचित है कि आपको किसी स्थिर चर में DateFormat को संग्रहीत नहीं करना चाहिए - या यदि आप करते हैं, तो आपको सिंक्रनाइज़ेशन की आवश्यकता होगी।
जॉन स्कीट

1
यह आम तौर पर बेहतर है - हालांकि अगर आपने सिंक्रोनाइज़ किया है तो स्टैटिक डेटफ़ॉर्मट होना ठीक रहेगा । यह SimpleDateFormatबहुत बार नया बनाने की तुलना में कई मामलों में बेहतर प्रदर्शन कर सकता है । यह उपयोग पैटर्न पर निर्भर करेगा।
जॉन स्कीट

1
क्या आप यह बता सकते हैं कि स्थिर और बहु-थ्रेडेड वातावरण में कैसे और क्यों समस्याएँ पैदा कर सकती हैं?
अलेक्जेंड्रा

4
क्योंकि यह उदाहरण चर में मध्यवर्ती गणना करता है, और यह थ्रेड-सुरक्षित नहीं है
Bozho

2

दिनांक प्रारूप सिंक्रनाइज़ नहीं हैं। प्रत्येक थ्रेड के लिए अलग प्रारूप इंस्टेंसेस बनाने की अनुशंसा की जाती है। यदि कई सूत्र समवर्ती रूप से एक प्रारूप का उपयोग करते हैं, तो इसे बाह्य रूप से सिंक्रनाइज़ किया जाना चाहिए।

इसका मतलब यह है कि आपके पास DateFormat की एक वस्तु है और आप दो अलग-अलग थ्रेड्स से एक ही ऑब्जेक्ट को एक्सेस कर रहे हैं और आप उस फॉर्मेट मेथड को कॉल कर रहे हैं, उस ऑब्जेक्ट पर दोनों थ्रेड्स एक ही समय पर एक ही विधि पर एक ही ऑब्जेक्ट में प्रवेश करेंगे, ताकि आप इसे जीते जाने की कल्पना कर सकें 'उचित परिणाम में नहीं

अगर आपको DateFormat के साथ काम करना है तो आपको कुछ करना चाहिए

public synchronized myFormat(){
// call here actual format method
}

1

डेटा दूषित है। कल मैंने इसे अपने मल्टीथ्रेड प्रोग्राम में देखा, जहां मेरे पास स्थिर DateFormatवस्तु थी और इसके format()मूल्यों को जेडीबीसी के माध्यम से पढ़े जाने के लिए बुलाया । मेरे पास SQL ​​चयन कथन था जहां मैंने अलग-अलग नामों ( SELECT date_from, date_from AS date_from1 ...) के साथ एक ही तारीख को पढ़ा । इस तरह के बयान 5 धागे में विभिन्न तिथियों के लिए उपयोग कर रहे थेWHERE क्लैस्यू । तिथियां "सामान्य" दिखती थीं, लेकिन वे मूल्य में भिन्न थे - जबकि सभी तिथियां एक ही वर्ष से थीं, केवल महीने और दिन बदल गए थे।

अन्य उत्तर आपको इस तरह के भ्रष्टाचार से बचने का रास्ता दिखाते हैं। मैंने अपना DateFormatस्टेटिक नहीं बनाया , अब यह एक वर्ग का सदस्य है जो एसक्यूएल स्टेटमेंट कहता है। मैंने सिंक्रनाइज़ेशन के साथ स्थिर संस्करण का भी परीक्षण किया। दोनों ने प्रदर्शन में कोई अंतर नहीं होने के साथ अच्छा काम किया।


1

प्रारूप, नंबरफ़ॉर्मैट, डेटफ़ॉर्मैट, संदेशफ़ॉर्मैट, आदि के विनिर्देशों को थ्रेड-सुरक्षित होने के लिए डिज़ाइन नहीं किया गया था। इसके अलावा, पार्स विधि विधि पर कॉल करती Calendar.clone()है और यह कैलेंडर के पैरों के निशान को प्रभावित करती है इसलिए कई धागे समवर्ती रूप से कैलेंडर उदाहरण के क्लोनिंग को बदल देंगे।

अधिक के लिए, ये बग रिपोर्ट हैं जैसे कि यह और यह , DateFormat थ्रेड-सुरक्षा समस्या के परिणामों के साथ।


1

सबसे अच्छा जवाब में डोगबेन ने parseफ़ंक्शन का उपयोग करने का एक उदाहरण दिया और इससे क्या होता है। नीचे एक कोड है जिसे आप formatफ़ंक्शन को चेक करते हैं।

ध्यान दें कि यदि आप निष्पादक (समवर्ती धागे) की संख्या बदलते हैं तो आपको अलग परिणाम मिलेंगे। मेरे प्रयोगों से:

  • newFixedThreadPoolसेट 5 पर छोड़ दें और लूप हर बार विफल हो जाएगा।
  • 1 पर सेट करें और लूप हमेशा काम करेगा (जाहिर है क्योंकि सभी कार्य वास्तव में एक-एक करके चलते हैं)
  • 2 पर सेट करें और लूप में केवल 6% काम करने की संभावना है।

मैं आपके प्रोसेसर के आधार पर YMMV का अनुमान लगा रहा हूं।

formatसमारोह एक अलग धागे से समय फ़ॉर्मेट करके विफल रहता है। ऐसा इसलिए है क्योंकि आंतरिक रूप से formatफ़ंक्शन calendarऑब्जेक्ट का उपयोग कर रहा है जो formatफ़ंक्शन के प्रारंभ में सेट किया गया है। और calendarवस्तु SimpleDateFormatवर्ग की एक संपत्ति है । आह ...

/**
 * Test SimpleDateFormat.format (non) thread-safety.
 *
 * @throws Exception
 */
private static void testFormatterSafety() throws Exception {
    final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    final Calendar calendar1 = new GregorianCalendar(2013,1,28,13,24,56);
    final Calendar calendar2 = new GregorianCalendar(2014,1,28,13,24,56);
    String expected[] = {"2013-02-28 13:24:56", "2014-02-28 13:24:56"};

    Callable<String> task1 = new Callable<String>() {
        @Override
        public String call() throws Exception {
            return "0#" + format.format(calendar1.getTime());
        }
    };
    Callable<String> task2 = new Callable<String>() {
        @Override
        public String call() throws Exception {
            return "1#" + format.format(calendar2.getTime());
        }
    };

    //pool with X threads
    // note that using more then CPU-threads will not give you a performance boost
    ExecutorService exec = Executors.newFixedThreadPool(5);
    List<Future<String>> results = new ArrayList<>();

    //perform some date conversions
    for (int i = 0; i < 1000; i++) {
        results.add(exec.submit(task1));
        results.add(exec.submit(task2));
    }
    exec.shutdown();

    //look at the results
    for (Future<String> result : results) {
        String answer = result.get();
        String[] split = answer.split("#");
        Integer calendarNo = Integer.parseInt(split[0]);
        String formatted = split[1];
        if (!expected[calendarNo].equals(formatted)) {
            System.out.println("formatted: " + formatted);
            System.out.println("expected: " + expected[calendarNo]);
            System.out.println("answer: " + answer);
            throw new Exception("formatted != expected");
        /**
        } else {
            System.out.println("OK answer: " + answer);
        /**/
        }
    }
    System.out.println("OK: Loop finished");
}

0

यदि किसी एकल DateFormat उदाहरण और सिंक्रनाइज़ेशन तक पहुंचने के लिए कई थ्रेड्स में हेरफेर / एक्सेस हो रहा है, तो स्क्रैम्बल परिणाम प्राप्त करना संभव है। ऐसा इसलिए है क्योंकि कई गैर-परमाणु संचालन राज्य को बदल सकते हैं या स्मृति को असंगत रूप से देख सकते हैं।


0

यह मेरा सरल कोड है जो दर्शाता है कि DateFormat थ्रेड सुरक्षित नहीं है।

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class DateTimeChecker {
    static DateFormat df = new SimpleDateFormat("EEE MMM dd kk:mm:ss z yyyy", Locale.ENGLISH);
    public static void main(String args[]){
       String target1 = "Thu Sep 28 20:29:30 JST 2000";
       String target2 = "Thu Sep 28 20:29:30 JST 2001";
       String target3 = "Thu Sep 28 20:29:30 JST 2002";
       runThread(target1);
       runThread(target2);
       runThread(target3);
   }
   public static void runThread(String target){
       Runnable myRunnable = new Runnable(){
          public void run(){

            Date result = null;
            try {
                result = df.parse(target);
            } catch (ParseException e) {
                e.printStackTrace();
                System.out.println("Ecxfrt");
            }  
            System.out.println(Thread.currentThread().getName() + "  " + result);
         }
       };
       Thread thread = new Thread(myRunnable);

       thread.start();
     }
}

चूंकि सभी थ्रेड्स एक ही SimpleDateFormat ऑब्जेक्ट का उपयोग कर रहे हैं, यह निम्न अपवाद फेंकता है।

Exception in thread "Thread-0" Exception in thread "Thread-2" Exception in thread "Thread-1" java.lang.NumberFormatException: multiple points
at sun.misc.FloatingDecimal.readJavaFormatString(Unknown Source)
at sun.misc.FloatingDecimal.parseDouble(Unknown Source)
at java.lang.Double.parseDouble(Unknown Source)
at java.text.DigitList.getDouble(Unknown Source)
at java.text.DecimalFormat.parse(Unknown Source)
at java.text.SimpleDateFormat.subParse(Unknown Source)
at java.text.SimpleDateFormat.parse(Unknown Source)
at java.text.DateFormat.parse(Unknown Source)
at DateTimeChecker$1.run(DateTimeChecker.java:24)
at java.lang.Thread.run(Unknown Source)
java.lang.NumberFormatException: multiple points
at sun.misc.FloatingDecimal.readJavaFormatString(Unknown Source)
at sun.misc.FloatingDecimal.parseDouble(Unknown Source)
at java.lang.Double.parseDouble(Unknown Source)
at java.text.DigitList.getDouble(Unknown Source)
at java.text.DecimalFormat.parse(Unknown Source)
at java.text.SimpleDateFormat.subParse(Unknown Source)
at java.text.SimpleDateFormat.parse(Unknown Source)
at java.text.DateFormat.parse(Unknown Source)
at DateTimeChecker$1.run(DateTimeChecker.java:24)
at java.lang.Thread.run(Unknown Source)
java.lang.NumberFormatException: multiple points
at sun.misc.FloatingDecimal.readJavaFormatString(Unknown Source)
at sun.misc.FloatingDecimal.parseDouble(Unknown Source)
at java.lang.Double.parseDouble(Unknown Source)
at java.text.DigitList.getDouble(Unknown Source)
at java.text.DecimalFormat.parse(Unknown Source)
at java.text.SimpleDateFormat.subParse(Unknown Source)
at java.text.SimpleDateFormat.parse(Unknown Source)
at java.text.DateFormat.parse(Unknown Source)
at DateTimeChecker$1.run(DateTimeChecker.java:24)
at java.lang.Thread.run(Unknown Source)

लेकिन अगर हम अलग-अलग ऑब्जेक्ट को अलग-अलग थ्रेड में पास करते हैं, तो कोड बिना त्रुटियों के चलता है।

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class DateTimeChecker {
    static DateFormat df;
    public static void main(String args[]){
       String target1 = "Thu Sep 28 20:29:30 JST 2000";
       String target2 = "Thu Sep 28 20:29:30 JST 2001";
       String target3 = "Thu Sep 28 20:29:30 JST 2002";
       df = new SimpleDateFormat("EEE MMM dd kk:mm:ss z yyyy", Locale.ENGLISH);
       runThread(target1, df);
       df = new SimpleDateFormat("EEE MMM dd kk:mm:ss z yyyy", Locale.ENGLISH);
       runThread(target2, df);
       df = new SimpleDateFormat("EEE MMM dd kk:mm:ss z yyyy", Locale.ENGLISH);
       runThread(target3, df);
   }
   public static void runThread(String target, DateFormat df){
      Runnable myRunnable = new Runnable(){
        public void run(){

            Date result = null;
            try {
                result = df.parse(target);
            } catch (ParseException e) {
                e.printStackTrace();
                System.out.println("Ecxfrt");
            }  
            System.out.println(Thread.currentThread().getName() + "  " + result);
         }
       };
       Thread thread = new Thread(myRunnable);

       thread.start();
   }
}

ये परिणाम हैं।

Thread-0  Thu Sep 28 17:29:30 IST 2000
Thread-2  Sat Sep 28 17:29:30 IST 2002
Thread-1  Fri Sep 28 17:29:30 IST 2001

ओपी ने पूछा कि ऐसा क्यों होता है।
एडम

0

यह कारण होगा ArrayIndexOutOfBoundsException

गलत परिणाम के अलावा, यह आपको समय-समय पर दुर्घटना देगा। यह आपकी मशीन की गति पर निर्भर करता है; मेरे लैपटॉप में, यह औसतन 100,000 कॉल में एक बार होता है:

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

ExecutorService executorService = Executors.newFixedThreadPool(2);
Future<?> future1 = executorService.submit(() -> {
  for (int i = 0; i < 99000; i++) {
    sdf.format(Date.from(LocalDate.parse("2019-12-31").atStartOfDay().toInstant(UTC)));
  }
});

executorService.submit(() -> {
  for (int i = 0; i < 99000; i++) {
    sdf.format(Date.from(LocalDate.parse("2020-04-17").atStartOfDay().toInstant(UTC)));
  }
});

future1.get();

अंतिम पंक्ति ने स्थगित निष्पादक अपवाद को ट्रिगर किया:

java.lang.ArrayIndexOutOfBoundsException: Index 16 out of bounds for length 13
  at java.base/sun.util.calendar.BaseCalendar.getCalendarDateFromFixedDate(BaseCalendar.java:453)
  at java.base/java.util.GregorianCalendar.computeFields(GregorianCalendar.java:2394)
  at java.base/java.util.GregorianCalendar.computeFields(GregorianCalendar.java:2309)
  at java.base/java.util.Calendar.complete(Calendar.java:2301)
  at java.base/java.util.Calendar.get(Calendar.java:1856)
  at java.base/java.text.SimpleDateFormat.subFormat(SimpleDateFormat.java:1150)
  at java.base/java.text.SimpleDateFormat.format(SimpleDateFormat.java:997)
  at java.base/java.text.SimpleDateFormat.format(SimpleDateFormat.java:967)
  at java.base/java.text.DateFormat.format(DateFormat.java:374)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.