What exactly is a resource leak? - java.util.scanner

i am using the Scanner class, and keep coming across warnings, saying I should close a resource leak. It has not affected me before, so I have disregarded it. Will this cause any problems for me in the future? How do I close the Scanner?

Scanner will not leak any resources, if the underlying object you use to initialise the scanner with is not leaking. You receive a compiler warning, since Scanner implements Closable and the interface specifies, that a (for lack of another word) resource must be closed after its use. Usually you will want to use a try-with-resources statement to automatically close the resource at the end of scope.
try (Scanner scanner = new Scanner("my input string")) {
while (scanner.hasNext()) {
process(scanner.next());
}
}
Reference: https://docs.oracle.com/javase/7/docs/api/java/io/Closeable.html

You need to close your scanner class:
Scanner in = new Scanner(System.in);
in.close(); //Here you're closing it
You can try using your scanner within a try/catch block to ensure that you will always close your scanner:
Scanner in = new Scanner(System.in);
try {
//Use your Scanner
} finally {
in.close();
}

Related

NUnit OneTimeTearDown Garbage collection best practice

At first, I have declared the variables at the beginning of my class
private AddressRepository sut;
private Mock<TransactionDbContext> mockDBContext;
In the OneTimeSetUp, I have created the set up code
[OneTimeSetUp]
public void Setup()
{
var options = new DbContextOptionsBuilder<TransactionDbContext>().Options;
mockDBContext = new Mock<TransactionDbContext>(options);
var dbSetMock = new Mock<DbSet<Address>>();
var data = ValueTask.FromResult(new Address() { AddressLine1 = "address line 1"
});
dbSetMock.Setup(s => s.FindAsync(It.IsAny<Guid>())).Returns(data);
mockDBContext.Setup(s => s.Set<Address>()).Returns(dbSetMock.Object);
}
Question, do I need to write additional code to handle garbage collection, or should I unassign all variables as following to speeds up GC?
[OneTimeTearDown]
public void TearDown()
{
//unassign all variables
mockDBContext = null;
sut = null;
//Possibly call GC.Collect?
GC.Collect();
}
Any coding advice will be well appreciated.
You should dispose of any disposable external resources, which you acquire. Where you do this depends on where you acquire the resource.
If you acquire it in your test fixture constructor, then let NUnit dispose of it. You do that by having the fixture class implement IDispose.
If you acquire it in a OneTimeSetUp, then dispose of it in the corresponding OneTimeTearDown.
If you acquire it in a SetUp, then dispose of it in the corresponding TearDown.
If you acuire it in a TestMethod, then dispose of it before that method returns. The simplest way to do this is via using.
All that said and explained, your example doesn't seem to acquire any disposable external resources. So I would not do any of those things. :-)
Generally, the time people spend figuring out overly complicated code outweighs any small advantage in efficiency. So wait till you see a performance problem before you fix it.

append huge volume of text to javafx TextArea from another thread (i.e. javafx task)

I'm creating a simple text editor application like ms notepad using JavaFX. I want it to handle large files maximum of 10mb, to do this I have created a task using the JavaFX concurrent package. The task will read the file using a buffered reader and append it to the text area.
My problem is that when I run the task with small files like 8kb to 10kb it works perfectly but when I increase the file size UI starts freezing and after reading few lines it stops working and I have to force stop the program.
Here is the code of task I have created...
public class ReadFile extends Task<String> {
private TextArea writingPad;
private File source;
public ReadFile(TextArea writingPad, File source) {
this.writingPad = writingPad;
this.source = source;
}
#Override
protected String call() throws Exception {
if (source != null && Files.exists(source.toPath())) {
if (source.isFile()) {
if (source.canRead()) {
if ((source.length() / (1024 * 1024)) <= 10) {
try (BufferedReader reader = new BufferedReader(new FileReader(source.getAbsolutePath()))) {
writingPad.clear();
updateTitle("Reading " + source.getName() + "...");
int workDone = 0;
char[] buffer = new char[8192];
int read;
while ((read = reader.read(buffer, 0, 8192)) >= 0) {
writingPad.appendText(String.valueof(buffer, 0, 8192));
workDone += read;
updateProgress(workDone, source.length());
}
} catch (IOException ignored) {
}
} else {
System.out.println("File is loo large.");
}
} else {
System.out.println("Can't read file.");
}
} else {
System.out.println("Is a directory.");
}
} else {
System.out.println("Is null");
}
return null;
}}
The above code throws exceptions like NullPointerException and IndexOuofBoundException so to solve this exception i have used this -> Platform.runLater(() -> writingPad.appendText(String.valueOf(buffer, 0, finalread))); Thread.sleep(100); method, but it also doesn't help me to achieve my goal properly. As it has solved the problem of exception but it takes too much time to read even small files and for large files problem is still the same. I have searched the internet but I didn't get any solution which can solve my problem.
So here is what I want:-
I want an effective and efficient way to read a text file (max size
10mb) and display its content in a text area.
The whole process of reading and writing is going to take place
from another thread (i.e a JavaFX task) so UI should not freeze
during the process.
As my application is a text editor so, no other UI component like
listview is going to be helpful.
Please suggest me a simple and easy solution as I'm new to JavaFX and multithreading.
Thanks
This is an excerpt from the javadoc of the Task class:
"An implementation of Task must override the call() method. This method is invoked on the background thread. Any state which is used in this method must be safe to read and write from a background thread. For example, manipulating a live scene graph from this method is unsafe and will result in runtime exceptions."
This should make it clear why your code is completely wrong.

Streamwriter, StringBuilder and Parallel loops

Sorry for big chunk of code, I couldn't explain that with less.Basically I'm trying to write into a file from many tasks.
Can you guys please tell me what I'm doing wrong? _streamWriter.WriteLine() throws the ArgumentOutOfRangeException.
class Program
{
private static LogBuilder _log = new LogBuilder();
static void Main(string[] args)
{
var acts = new List<Func<string>>();
var rnd = new Random();
for (int i = 0; i < 10000; i++)
{
acts.Add(() =>
{
var delay = rnd.Next(300);
Thread.Sleep(delay);
return "act that that lasted "+delay;
});
}
Parallel.ForEach(acts, act =>
{
_log.Log.AppendLine(act.Invoke());
_log.Write();
});
}
}
public class LogBuilder : IDisposable
{
public StringBuilder Log = new StringBuilder();
private FileStream _fileStream;
private StreamWriter _streamWriter;
public LogBuilder()
{
_fileStream = new FileStream("log.txt", FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
_streamWriter = new StreamWriter(_fileStream) { AutoFlush = true };
}
public void Write()
{
lock (Log)
{
if (Log.Length <= 0) return;
_streamWriter.WriteLine(Log.ToString()); //throws here. Although Log.Length is greater than zero
Log.Clear();
}
}
public void Dispose()
{
_streamWriter.Close(); _streamWriter.Dispose(); _fileStream.Close(); fileStream.Dispose();
}
}
This is not a bug in StringBuilder, it's a bug in your code. And the modification you shown in your followup answer (where you replace Log.String with a loop that extracts characters one at a time) doesn't fix it. It won't throw an exception any more, but it won't work properly either.
The problem is that you're using the StringBuilder in two places in your multithreaded code, and one of them does not attempt to lock it, meaning that reading can occur on one thread simultaneously with writing occurring on another. In particular, the problem is this line:
_log.Log.AppendLine(act.Invoke());
You're doing that inside your Parallel.ForEach. You are not making any attempt at synchronization here, even though this will run on multiple threads at once. So you've got two problems:
Multiple calls to AppendLine may be in progress simultaneously on multiple threads
One thread may attempt to be calling Log.ToString at the same time as one or more other threads are calling AppendLine
You'll only get one read at a time because you are using the lock keyword to synchronize those. The problem is that you're not also acquiring the same lock when calling AppendLine.
Your 'fix' isn't really a fix. You've succeeded only in making the problem harder to see. It will now merely go wrong in different and more subtle ways. For example, I'm assuming that your Write method still goes on to call Log.Clear after your for loop completes its final iteration. Well in between completing that final iteration, and making the call to Log.Clear, it's possible that some other thread will have got in another call to AppendLine because there's no synchronization on those calls to AppendLine.
The upshot is that you will sometimes miss stuff. Code will write things into the string builder that then get cleared out without ever being written to the stream writer.
Also, there's a pretty good chance of concurrent AppendLine calls causing problems. If you're lucky they will crash from time to time. (That's good because it makes it clear you have a problem to fix.) If you're unlucky, you'll just get data corruption from time to time - two threads may end up writing into the same place in the StringBuilder resulting either in a mess, or completely lost data.
Again, this is not a bug in StringBuilder. It is not designed to support being used simultaneously from multiple threads. It's your job to make sure that only one thread at a time does anything to any particular instance of StringBuilder. As the documentation for that class says, "Any instance members are not guaranteed to be thread safe."
Obviously you don't want to hold the lock while you call act.Invoke() because that's presumably the very work you want to parallelize. So I'd guess something like this might work better:
string result = act();
lock(_log.Log)
{
_log.Log.AppendLine(result);
}
However, if I left it there, I wouldn't really be helping you, because this looks very wrong to me.
If you ever find yourself locking a field in someone else's object, it's a sign of a design problem in your code. It would probably make more sense to modify the design, so that the LogBuilder.Write method accepts a string. To be honest, I'm not even sure why you're using a StringBuilder here at all, as you seem to use it just as a holding area for a string that you immediately write to a stream writer. What were you hoping the StringBuilder would add here? The following would be simpler and doesn't seem to lose anything (other than the original concurrency bugs):
public class LogBuilder : IDisposable
{
private readonly object _lock = new object();
private FileStream _fileStream;
private StreamWriter _streamWriter;
public LogBuilder()
{
_fileStream = new FileStream("log.txt", FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
_streamWriter = new StreamWriter(_fileStream) { AutoFlush = true };
}
public void Write(string logLine)
{
lock (_lock)
{
_streamWriter.WriteLine(logLine);
}
}
public void Dispose()
{
_streamWriter.Dispose(); fileStream.Dispose();
}
}
I think the cause is because you are accessing the stringBuilder in the Parellel bracket
_log.Log.AppendLine(act.Invoke());
_log.Write();
and inside the LogBuilder you perform lock() to disallow memory allocation on stringBuidler. You are changing the streamwriter to handle the log in every character so would give the parellel process to unlock the memory allocation to stringBuilder.
Segregate the parallel process into distinct action would likely reduce the problem
Parallel.ForEach(acts, act =>
{
_log.Write(act.Invoke());
});
in the LogBuilder class
private readonly object _lock = new object();
public void Write(string logLines)
{
lock (_lock)
{
//_wr.WriteLine(logLines);
Console.WriteLine(logLines);
}
}
An alternate approach is to use TextWriter.Synchronized to wrap StreamWriter.
void Main(string[] args)
{
var rnd = new Random();
var writer = new StreamWriter(#"C:\temp\foo.txt");
var syncedWriter = TextWriter.Synchronized(writer);
var tasks = new List<Func<string>>();
for (int i = 0; i < 1000; i++)
{
int local_i = i; // get a local value, not closure-reference to i
tasks.Add(() =>
{
var delay = rnd.Next(5);
Thread.Sleep(delay);
return local_i.ToString() + " act that that lasted " + delay.ToString();
});
}
Parallel.ForEach(tasks, task =>
{
var value = task();
syncedWriter.WriteLine(value);
});
writer.Dispose();
}
Here are some of the synchronization helper classes
http://referencesource.microsoft.com/#q=Synchronized
System.Collections
static ArrayList Synchronized(ArrayList list)
static IList Synchronized(IList list)
static Hashtable Synchronized(Hashtable table)
static Queue Synchronized(Queue queue)
static SortedList Synchronized(SortedList list)
static Stack Synchronized(Stack stack)
System.Collections.Generic
static IList Synchronized(List list)
System.IO
static Stream Synchronized(Stream stream)
static TextReader Synchronized(TextReader reader)
static TextWriter Synchronized(TextWriter writer)
System.Text.RegularExpressions
static Match Synchronized(Match inner)
static Group Synchronized(Group inner)
It is seems that it isn't problem of Parallelism. It's StringBuilder's problem.
I have replaced:
_streamWriter.WriteLine(Log.ToString());
with:
for (int i = 0; i < Log.Length; i++)
{
_streamWriter.Write(Log[i]);
}
And it worked.
For future reference: http://msdn.microsoft.com/en-us/library/system.text.stringbuilder(v=VS.100).aspx
Memory allocation section.

Java-ME Application in Freeze Mode

I am developing a Java-ME Based Mobile Application. Now My Requirements are like whenever I am updating one of my RMS, I want my application to be stay in a Freeze kind of mode; which means no other action like clicking button or anything else should happen. My Method is already "Synchronized".
Kindly guide me regarding this question.
Thanks.
The best way to handle this is to "serialize" your tasks. You can do this with a message queue - a class that maintains a Vector of message objects (tasks) and runs code based on each message. The queue runs on a thread that processes each task (message) in series. You create a simple message class for the different tasks - read RMS etc. A message can be an Integer if you like that wraps a number. The operation of adding and retrieving messages is synchronized but the code than does the tasks is not and runs on a simple switch block. The benefit of serializing your tasks is you don't have to worry about concurrency. Here is some of the essential code from a class I use to do this.
class MessageQueue implements Runnable{
Vector messages;
Thread myThread;
volatile boolean stop;
public void start() {
stop=false;
myThread=new Thread(this);
myThread.start();
}
// add message to queue - this is public
public synchronized void addMessage(Message m) {
messages.addElement(m);
if(stop) {
start();
} else {
// wake the thread
notify();
}
}
// get next message from queue - used by this thread
private synchronized Message nextMessage() {
if(stop) return null;
if(messages.isEmpty()) {
return null;
} else {
Message m=(Message)messages.firstElement();
messages.removeElementAt(0);
return m;
}
}
public void run() {
while (!stop) {
// make thread wait for messages
if (messages.size() == 0) {
synchronized (this) {
try {
wait();
} catch (Exception e) {
}
}
}
if (stop) {
// catch a call to quit
return;
}
processMessage();
}
}
}
// all the tasks are in here
private void processMessage() {
Message m = nextMessage();
switch (m.getType()) {
case Message.TASK1:
// do stuff
break;
case Message.TASK2:
// do other stuff
break;
case Message.TASK3:
// do other other stuff
break;
default: //handle bad message
}
}
}
What you are asking is very code depended. Usually when you want to make some synchronic actions you just write them one after the other. in java it's more complected, since sometimes you "ask" the system to do something (like repaint() method). But since the RMS read/write operations are very quick (few millisecond) i don't see any need in freesing.
Could you please provide some more information about the need (time for RMS to respond)? does your code runs on system thread (main thread) or your own thread?
I want my application to be stay in a Freeze kind of mode; which means no other action like clicking button or anything else should happen.
First of all I would strongly advise against real freezing of UI - this could make a suicidal user experience for your application.
If you ever happened to sit in front of computer frozen because of some programming bug, you may understand why approach like this is strongly discouraged. As they describe it in MIDP threading tutorial, "user interface freezes, the device appears to be dead, and the user becomes frustrated..."
This tutorial by the way also suggests possibly the simplest solution for problems like you describe: displaying a wait screen. If you don't really have reasons to avoid this solution, just do as tutorial suggests.
To be on a safe side, consider serializing tasks as suggested in another answer. This will ensure that when RMS update starts, there are no other tasks pending.

Opening multiple sessions simultaneously in NHibernate

I finally figured out what's wrong with my code, but I'm not sure how to fix it. I have some background processes running on a separate thread that perform some database maintenance tasks. Here's an exmple of what's happening:
//Both processes share the same instance of ISessionFactory
//but open separate ISessions
//This is running on it's own thread
public void ShortRunningTask()
{
using(var session = _sessionFactory.OpenSession())
{
//Do something quickly here
session.Update(myrecord);
}
}
//This is running on another thread
public void LongRunningTask()
{
using(var session = _sessionFactory.OpenSession())
{
//Do something long here
}
}
Let's say I start LongRunningTask first. While it's running I start ShortRunningTask on another thread. ShortRunningTask finishes up and closes its session. Once LongRunningTask finishes it tries to do something with it's session it created but an error get's thrown saying that the session has already been closed.
Clearly what's happening is that ISessionFactory.OpenSession() is not honoring the fact that I've opened 2 separate sessions. Closing the session opened in ShortRunningTask also closes the session in LongRunningTask How can I fix this? Please help!
Thanks!
UPDATE
So apparently everyone thinks my fix is totally wrong. So here's the configuration I am using:
_sessionFactory = Fluently.Configure()
.Database(
FluentNHibernate.Cfg.Db.MsSqlConfiguration.MsSql2008
.ConnectionString(db => db.Is(
WikipediaMaze.Core.Properties.Settings.Default.WikipediaMazeConnection)))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<IRepository>())
.BuildSessionFactory();
I have no configuration taking place in an xml file. Should there be? What am I missing. Here's another example of how opening multiple sessions fails:
public void OpenMultipleSessionsTest()
{
using(var session1 = _sessionFactory.OpenSession())
{
var user = session1.Get<Users>().ById(1);
user.Name = "New Name";
using(var session2 = _sessionFactory.OpenSession())
{
//Do some other operation here.
}
session1.Update(user);
session1.Flush(); // Throws error 'ISession already closed!'
}
}
I figured out how to fix the problem. I setup my SessionFactory as a singleton at made it [ThreadStatic] like this:
[ThreadStatic]
private ISessionFactory _sessionFactory;
[ThreadStatic]
private bool _isInitialized;
public ISessionFactory SessionFactory
{
get
{
if(!_isInitialized)
{
//Initialize the session factory here
}
}
}
The crux of the problem is that creating sessions on separate threads from the same ISessionFactory is problematic. ISessionFactory does not like multiple ISessions being opened at the same time. Closing one, automatically closes any others that are open. Using the [ThreadStatic] attribute creates a separate ISessionFactory for each thread. This allows me to open and close ISessions on each thread without affecting the others.

Resources