We help IT Professionals succeed at work.

java.nio.channels.NonWritableChannelException thrown when requesting a FileChannel Lock

Tony O'Byrne
Tony O'Byrne asked
on
6,701 Views
Last Modified: 2012-05-06
Hi all,

I'm trying to learn how to use file locks.  The examples on the web seem to be pretty straightforward, but when I try to use locks in my code, I get the NonWritableChannelException error.

So far I'm just trying to create and release the FileChannel and the lock in some existing code I'm working on.  As you can imagine from the code below, the System.out.printlns are there just so I can see in the output where things are happening.

In the bigger picture, the code is supposed to read a JTree from the disk, cast it to JTree and, in later code, refresh the tree to reflect the loaded info.  The plan is for multiple people to use this application over a network and be able to save any changes.  This is my first time using file locks.

Anyone have any ideas?
try{
	FileInputStream fin = new FileInputStream( reply ) ;
	System.out.println( "1" ) ;
	FileChannel channel = fin.getChannel( ) ;
	System.out.println( "2" ) ;
	FileLock lock = channel.tryLock( 0, channel.size( ), false ) ; -- Line 226
	System.out.println( "3" ) ;
 
	if( lock == null ){
		throw new Error( "No Lock. :(" ) ;
	}
	
	ObjectInputStream objin = new ObjectInputStream( fin ) ;
	equipmentTree = (JTree)objin.readObject( ) ;
 
	lock.release( ) ;
	channel.close( ) ;
	objin.close( ) ;
	fin.close( ) ;
}
catch( Exception e ){
	e.printStackTrace( System.out ) ;
	//	Reload the default tree
	reloadTree( ) ;
}
 
--------------------------------------------------
 
Output:
1
2
java.nio.channels.NonWritableChannelException
	at sun.nio.ch.FileChannelImpl.tryLock(Unknown Source)
	at DavitaTree.ProgUI.loadTree(DavitaUI.java:226)
	at DavitaTree.ProgMenu.actionPerformed(DavitaMenu.java:89)
	at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
	at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
	at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
	at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
	at javax.swing.AbstractButton.doClick(Unknown Source)
	at javax.swing.plaf.basic.BasicMenuItemUI.doClick(Unknown Source)
	at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(Unknown Source)
	at java.awt.Component.processMouseEvent(Unknown Source)
	at javax.swing.JComponent.processMouseEvent(Unknown Source)
	at java.awt.Component.processEvent(Unknown Source)
	at java.awt.Container.processEvent(Unknown Source)
	at java.awt.Component.dispatchEventImpl(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Window.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.run(Unknown Source)

Open in new window

Comment
Watch Question

Mick BarryJava Developer
CERTIFIED EXPERT
Top Expert 2010

Commented:
you trying to lock an input stream. input streams are read only

CERTIFIED EXPERT
Top Expert 2016

Commented:
Try creating the channel read-only:
FileChannel channel = new RandomAccessFile(reply, "r").getChannel();

Open in new window

Tony O'ByrneSenior Web Developer

Author

Commented:
Using RandomAccessFile I get the following error:
The constructor ObjectInputStream(RandomAccessFile) is undefined

If I use RandomAccessFile, I need some other way to read an object from a file.

I understand that input streams are read only, but why does that present issues when I try to obtain a lock?  Is lock information written to the file itself?  If I try to lock something that's read only, wouldn't CEHJ's comment also fail? (because of the RandomAccessFile(reply, "r") istead of being "rw"?)
ksivananthVice President

Commented:
>>Using RandomAccessFile I get the following error:
The constructor ObjectInputStream(RandomAccessFile) is undefined
>>

you can use the RandomAccessFile logic to lock the file and then use the stream to construct ObjectInputStream!
Tony O'ByrneSenior Web Developer

Author

Commented:
ksivananth,

I tried several things based on what you suggested, and considering my results, I guess I don't understand what you mean, or how to achieve what I think you mean.

I've tried creating the randomAccessFile and getting the lock, then creating the FileInputStream and reading in from there.  But I get a file is locked exception.  Which makes sense - I locked it.

I then tried reading the randomAccessFile into a few different types of InputStreams.  Some wouldn't accept the randomAccessFile as a parameter to the respective constructors, but I did see on the sun website (http://java.sun.com/javase/technologies/core/basic/serializationFAQ.jsp#random) that using ByteArray[Input|Output]Stream was the way to go.

So I tried the code posted below.  However I got:
[ java.io.StreamCorruptedException: invalid stream header: 00000000 ] on line 237.

Is the ByteArray[Input|Output]Stream the way to go with this?  Or did you have something else in mind?
try{
	RandomAccessFile raf = new RandomAccessFile( reply, "rw" ) ;
	FileChannel channel = raf.getChannel( ) ;
	FileLock lock = channel.tryLock( 0, channel.size( ), false ) ;
 
	if( lock == null ){
		throw new Error( "No Lock. :(" ) ;
	}
 
	byte[] byteArray = new byte[(int)raf.length( )] ;
	ByteArrayInputStream bais = new ByteArrayInputStream( byteArray ) ;
 
	ObjectInputStream objin = new ObjectInputStream( bais ) ;	--	Line 237
 
	equipmentTree = (JTree)objin.readObject( ) ;
 
	lock.release( ) ;
	channel.close( ) ;
	objin.close( ) ;
	raf.close( ) ;
}

Open in new window

Mick BarryJava Developer
CERTIFIED EXPERT
Top Expert 2010

Commented:
you can't use the file, you are already using it as a lock.
What is it you are trying to achieve?

Tony O'ByrneSenior Web Developer

Author

Commented:
The application will load the tree information when it starts up.  The application will be used on multiple computers over a network and will need this information.  The application is for the tracking of equipment that's moved around to different locations, so everyone who will be using the app needs to know what everyone else has done.  Therefore, everyone would ideally have access to the one datafile.

Naturally, if two people start working on it at the same time, weird things can happen if they load the same information, but then save different information.  So I want to lock the file when it's opened.  I know that in the code above I close the lock almost right away, but right now, I'm just concerned with getting the process down.

In the case of the single user, I want to open and read the file, make sure it's locked, and later, write the updated tree to the file, and release the lock.
Tony O'ByrneSenior Web Developer

Author

Commented:
I do understand that I may be going about this the wrong way...  That's why I'm here; I've never done this before.  I've looked at online examples, including the one mentioned above.  So far as I can see, some of the online examples have almost the exact same code that I posted at the start of this thread.  For example: http://stackoverflow.com/questions/421833/when-using-javas-filelock-is-it-ok-to-let-close-to-automatically-do-a-lock-re does the exact same thing as I do at the start - InputStream followed by Channel followed by Lock followed by read.
Java Developer
CERTIFIED EXPERT
Top Expert 2010
Commented:
This one is on us!
(Get your first solution completely free - no credit card required)
UNLOCK SOLUTION
Tony O'ByrneSenior Web Developer

Author

Commented:
Great! :-)  It all seems like it should be working - I've got my code exactly as you suggest, objects, but now, I'm getting an error on the line that actually reads the data -
ObjectInputStream objin = new ObjectInputStream( in ) ;

The error is:
java.io.IOException: The process cannot access the file because another process has locked a portion of the file

Any ideas as to what that other process may be?  It's particularly confusing to me since this process obviously has the lock.
ksivananthVice President
Commented:
This one is on us!
(Get your first solution completely free - no credit card required)
UNLOCK SOLUTION
Tony O'ByrneSenior Web Developer

Author

Commented:
Ok, it looks like we've finally gotten it working. :)
No exceptions thrown, no nothing - the tree loads real good.  All I need to do now is test and award points.

Thanks for all your help folks. :)

For anyone who stumbles upon this thread later, the code is below.
try{
	RandomAccessFile raf = new RandomAccessFile( reply, "rw" ) ;
	FileChannel channel = raf.getChannel( ) ;
	FileLock lock = channel.tryLock( 0, channel.size( ), false ) ;
 
	if( lock == null ){
		throw new Error( "No Lock. :(" ) ;
	}
 
	byte[] byteArray = new byte[(int)raf.length( )] ;
	ByteBuffer byteBuffer = ByteBuffer.wrap( byteArray ) ;
	channel.read( byteBuffer ) ;
 
	ByteArrayInputStream inStream = new ByteArrayInputStream( byteArray ) ;
 
	ObjectInputStream objin = new ObjectInputStream( inStream ) ;
 
	equipmentTree = (JTree)objin.readObject( ) ;
 
	inStream.close( ) ;
	lock.release( ) ;
	channel.close( ) ;
	objin.close( ) ;
	raf.close( ) ;
}

Open in new window

Tony O'ByrneSenior Web Developer

Author

Commented:
Thanks guys.  Your guidance without throwing a completed solution helped me figure out a solution that worked with my code.
All the best,
Tony. :)
ksivananthVice President

Commented:
Glad you got it working but the one you have accepted is not the right one!
Tony O'ByrneSenior Web Developer

Author

Commented:
I was trying to accept both, and award points to both objects and ksivananth...

The way I was reading, objects confirmed that I need to create the lock then use the stream after the lock, and in your response you said that the ByteArrayInputStream was the way to go, and to read through the channel.

If it's a matter of how the points were shared, I guess you did offer the larger portion of the solution - is it possible for me to change the points?  I guess I was trying to be sure that points were awarded for the contributions.  If it's a matter of which, and not whose, reply, well then I truly have no idea which one was the solution...

So far as I can understand, the general method was
Create lock
Read through Channel
Create inputStream (using ByteArrayInputStream)

This was my first ever post.  Help me understand how the etiquette goes? :-)

Gain unlimited access to on-demand training courses with an Experts Exchange subscription.

Get Access
Why Experts Exchange?

Experts Exchange always has the answer, or at the least points me in the correct direction! It is like having another employee that is extremely experienced.

Jim Murphy
Programmer at Smart IT Solutions

When asked, what has been your best career decision?

Deciding to stick with EE.

Mohamed Asif
Technical Department Head

Being involved with EE helped me to grow personally and professionally.

Carl Webster
CTP, Sr Infrastructure Consultant
Empower Your Career
Did You Know?

We've partnered with two important charities to provide clean water and computer science education to those who need it most. READ MORE

Ask ANY Question

Connect with Certified Experts to gain insight and support on specific technology challenges including:

  • Troubleshooting
  • Research
  • Professional Opinions
Unlock the solution to this question.
Join our community and discover your potential

Experts Exchange is the only place where you can interact directly with leading experts in the technology field. Become a member today and access the collective knowledge of thousands of technology experts.

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.