2010-08-30 13 views
10

मेरे पास JTable डिस्क पर राज्य को जारी रखने के लिए ज़िम्मेदार वस्तु है। यह दृश्य कॉलम, उनके आकार, स्थिति इत्यादि को बचाता/लोड करता है। इसकी कक्षा परिभाषा से कुछ रोचक बिट्स नीचे हैं।जावा ऑब्जेक्ट पर सिंक्रनाइज़ फ़ाइल एक्सेस

class TableSaver { 
    Timer timer = new Timer(true); 

    TableSaver() { 
     timer.schedule(new TableSaverTimerTask(), 15000, SAVE_STATE_PERIOD); 
    } 

    synchronized TableColumns load(PersistentTable table) { 
     String xml = loadFile(table.getTableKey()); 
     // parse XML, return 
    } 

    synchronized void save(String key, TableColumns value) { 
     try { 
      // Some preparations 
      writeFile(app.getTableConfigFileName(key), xml); 
     } catch (Exception e) { 
      // ... handle 
     } 
    } 

    private class TableSaverTimerTask extends TimerTask { 
     @Override 
     public void run() { 
      synchronized (TableSaver.this) { 
       Iterator<PersistentTable> iterator = queue.iterator(); 
       while (iterator.hasNext()) { 
        PersistentTable table = iterator.next(); 
        if (table.getTableKey() != null) { 
         save(table.getTableKey(), dumpState(table)); 
        } 
        iterator.remove(); 
       } 
      } 
     } 
    } 
} 
  • वहाँ केवल TableSaver का एक उदाहरण मौजूद है, कभी।
  • load() कई धागे से बुलाया जा सकता है। टाइमर स्पष्ट रूप से एक और धागा है।
  • loadFile() और writeFile() खुले फ़ाइल स्ट्रीम को न छोड़ें - वे एक मजबूत, अच्छी तरह से परीक्षण और व्यापक रूप से उपयोग की जाने वाली लाइब्रेरी का उपयोग करते हैं जो हमेशा try ... finally के साथ धाराओं को बंद करता है।

कभी कभी इस तरह एक अपवाद के साथ विफल:

  1. तुल्यकालन के इस प्रकार कैसे असफल हो सकता है:

    java.lang.RuntimeException: java.io.FileNotFoundException: C:\path\to\table-MyTable.xml (The requested operation cannot be performed on a file with a user-mapped section open) 
        at package.FileUtil.writeFile(FileUtil.java:33) 
        at package.TableSaver.save(TableSaver.java:175) 
        at package.TableSaver.access$600(TableSaver.java:34) 
        at package.TableSaver$TableSaverTimerTask.run(TableSaver.java:246) 
        at java.util.TimerThread.mainLoop(Unknown Source) 
        at java.util.TimerThread.run(Unknown Source) 
    Caused by: java.io.FileNotFoundException: C:\path\to\table-MyTable.xml (The requested operation cannot be performed on a file with a user-mapped section open) 
        at java.io.FileOutputStream.open(Native Method) 
        at java.io.FileOutputStream.<init>(Unknown Source) 
        at java.io.FileOutputStream.<init>(Unknown Source) 
        at package.FileUtilWorker.writeFile(FileUtilWorker.java:57) 
        ... 6 more 
    

    तो मैं दो प्रश्न हैं? ध्यान दें कि मुझे यकीन है कि केवल TableSaver का एक उदाहरण है।

  2. स्टैकट्रैक में यह बात क्या है: package.TableSaver.access$600(TableSaver.java:34)? लाइन 34 class TableSaver { के साथ लाइन है। क्या यह कारण हो सकता है कि सिंक्रनाइज़ेशन काम नहीं कर रहा है?
+0

आप पोस्ट कर सकते हैं अपने 'WriteFile()' कोड? –

+0

# 2 के संबंध में, कोई समस्या नहीं है। यह एक घोंसला वाले आंतरिक वर्ग से संलग्न वर्ग के एक निजी सदस्य को बुलाए जाने का एक संकलक आर्टेफैक्ट है। –

उत्तर

9

Google मुझे पता चलता है कि इस Windows विशिष्ट हो रहा है। यहाँ Bug 6354433 के एक उद्धरण है:

यह स्मृति-मैप की गई फ़ाइल के साथ विंडोज प्लेटफार्म मुद्दा है, यानी MappedByteBuffer है। FileChannel के लिए जावा 5.0 डॉक यह बताता है कि "बफर और मैपिंग जो यह दर्शाती है वह तब तक वैध रहेगी जब तक बफर स्वयं कचरा-संग्रह नहीं होता"। त्रुटि तब होती है जब हमने filestore को फिर से खोलने का प्रयास किया और मैप किए गए बाइट बफर जीसी नहीं किया गया है। चूंकि मैप किए गए बाइट बफर के लिए unmap() विधि नहीं है (बग 4724038 देखें), हम बफर मुक्त होने पर अंतर्निहित ऑपरेटिंग सिस्टम की दया पर हैं। कॉलिंग System.gc() बफर को मुक्त कर सकता है लेकिन इसकी गारंटी नहीं है। सोलारिस पर समस्या नहीं होती है; Solaris पर साझा स्मृति लागू करने के तरीके के कारण हो सकता है। तो विंडोज के लिए काम-आसपास लेनदेन सूचना तालिकाओं के लिए स्मृति-मैप की गई फ़ाइल का उपयोग नहीं करना है।

आप किस जावा/विंडोज संस्करण का उपयोग कर रहे हैं? क्या इसमें नवीनतम अपडेट हैं?मेमोरी मैप की फ़ाइल हटाया नहीं जा सकता -

  • Bug 4715154:

    यहाँ कुछ उपयोगी अंतर्दृष्टि के साथ दो अन्य संबंधित कीड़े हैं।

  • Bug 4469299 - मेमोरी मैप की गई फ़ाइलें जीसीएड नहीं हैं।

अपने दूसरे प्रश्न के रूप में, कि सिर्फ एक आंतरिक या अनाम वर्ग के स्वत: जनरेट की classname है।

+0

क्या होगा यदि मैं 'java.io.FileOutputStream' और 'java.io.FileInputStream' का उपयोग कर रहा हूं और एनआईओ नहीं? –

+0

यह हुड के नीचे एनआईओ का उपयोग कर रहा है। – BalusC

+0

तो हमें तब क्या उपयोग करना चाहिए? क्या आप मुझे डेस्कटॉप विंडोज 7 पर एक ही समस्या होने के बारे में बता सकते हैं जबकि लैपटॉप के साथ यह ठीक था, लिनक्स में कोई समस्या नहीं है। मैंने प्रिंटराइटर, bufferedwriter और nio का उपयोग किया, सभी को एक ही समस्या थी –

2

मान लें कि कोड में कोई वायरस स्कैनर चल रहा है, जो पृष्ठभूमि में चल रहा है, जो दृश्यों के पीछे उन्हें स्कैन करने के लिए फ़ाइलों को खुशी से खोल रहा है। यदि आपके पास मेमोरी निवासी वायरस स्कैनर है जो पृष्ठभूमि में फ़ाइलों को चेक करता है, तो इसे अक्षम करने का प्रयास करें, या कम से कम उस निर्देशिका के लिए अक्षम करें जिसे आप पढ़ रहे/लिखते हैं।

1

आपका कोड ठीक दिखता है। क्या आप वाकई फ़ाइल अनुमति से संबंधित नहीं हैं? क्या एप्लिकेशन के पास इस फ़ोल्डर को विशेषाधिकार है? इस फाइल के लिए?


[संपादित करें] यह करने के लिए Windows संबंधित हो लगता है, नहीं जावा The requested operation cannot be performed on a file with a user-mapped section open.

0

आपका सिंक्रनाइज़ेशन केवल आपकी प्रक्रिया से पहुंच के विरुद्ध सुरक्षा करता है। आप किसी भी प्रक्रिया से पहुंच के खिलाफ की रक्षा करना चाहते हैं, तो आप में ताला फ़ाइल का उपयोग करना होगा:

http://download.oracle.com/javase/1.4.2/docs/api/java/nio/channels/FileLock.html

0

मैं कुछ कसकर पिरोया जावा कोड के साथ इस मुद्दे था। मैंने संदर्भित .NET बातचीत और पैनी गिरावट पर एक नज़र डाली। यह बस इतना है कि मेरे पास अलग-अलग धागे के बीच एक ही फाइल के लिए विवाद है। कुछ आंतरिक रूप से विवाद (भी) पर अधिक बारीकी से देख रहे हैं। इसलिए मेरा सबसे अच्छा कोर्स सिंक्रनाइज़-डी साझा ऑब्जेक्ट के आसपास अपडेट होने पर है।

यह काम करता है और त्रुटि धुंध में घुल जाती है।

private static ShortLog tasksLog  = new ShortLog("filename"); 
    private static Boolean tasksLogLock = false; 

     ... 

    synchronized(tasksLogLock){ 
     tasksLog.saveLastDatum(this.toString()); 
    } 

भी देखें:

संबंधित मुद्दे