Constructor yields null - where to start? - java

I am creating a set of TestNG tests in eclipse for existing code that supposedly validates certificates against a CRL.
In my test, I create a new class to provide validation functions, like this:
public void testRevokedCertificate() throws Exception {
EmbeddedFileServer embeddedFileServer = new EmbeddedFileServer(CertificateResourceHelper.getResourcePath("."));
embeddedFileServer.start();
URL crlUrl = new URL("http://localhost:" + embeddedFileServer.getPort() + "/certs/" + "test_ca1.crl");
CachingValidCrlProvider prov = new CachingValidCrlProvider(crlUrl, publicKey, 1, 2);
assertNotNull(prov);
}
The constructor CachingValidCrlProvider(URL, publicKey, int, int) always returns null! This is a mystery to me, as the constructor does not look very special:
public CachingValidCrlProvider(URL crlUrl, PublicKey expectedPublicKey, int failedDownloadBackoffTimeInSeconds, int forcedCrlRefreshIntervalInSeconds) {
System.out.println("Creating CachingValidCrlProvider (this is never displayed)");
this.crlUrl = crlUrl;
this.expectedPublicKey = expectedPublicKey;
crlDownloadState = new CrlDownloadState(failedDownloadBackoffTimeInSeconds, forcedCrlRefreshIntervalInSeconds);
}
The first debug println() is somehow never reached since I cannot find the printed line in stdout.
AFAIK, one of the few ways constructors may yield null is when a static {} block fails somewhere down the line. However, I do not see any (there is one such block in the codebase but not reachable in this scenario).
How do I troubleshoot this issue?

Quote from an answer here on StackOverflow by Jon Skeet:
From section 15.9.4 of the JLS:
The value of a class instance creation expression is a reference to the newly created object of the specified class. Every time the expression is evaluated, a fresh object is created.
So no, it can never return null.
A constructor in Java CANNOT return null. The only case your object can be null is if you didn't call the constructor, or the constructor raised an exception.
EDIT:
As for your code, the most probable possibility IMO is that the code doesn't stop on your assertNotNull(prov), but never reaches it and instead crashes somewhere before. You should try using the debugger/more sysout.

Static Initialization Blocks are executed before anything else, So the code is reached, you just don't know it. I suggest you add a breakpoint in your static block, and use a debugger (included in eclipse or Intellij) to see when it fails. good luck.

Thank you all for the responses. They helped me get to the root cause. As it turned out, there was a mock initialization of this class in another test (there are ~300 existing tests by other people in this codebase).
Because the code uses singletons extensively, my call to new did not actually change anything to the already-initialized object.
I found this thanks to your remarks and hints which made me look in different parts of the codebase, thanks a lot.

Related

Weird negative length array created into Class.getDeclaredFields that makes JVM to throw a NegativeArraySizeException

I Use Java 15 openjdk and tried on Java 14
Include details about your goal
I'm making a RMI system in order to make instances of any object synchronisable between computers and make multiple engines works on the same object. With my system, when i want to synchronise an object, i generate a class that will extends the object class and then override every methods of the class in order to control if the method call must be delegated to the object or to perform a RMI request instead.
The class generation is divided in two part :
I generate the source code in which every non-final methods are overriden in order to add my delegating system. the code is generated in scala language, and this class yet does not extends from the class of the object to synchronise because scala don't let me override some methods, even if they are not final (it's a thing with scala's setters and getters), then i compile the code using the Scala Compiler.
I use javassist to modify the generated class and make it extends the expected class + i add some methods and modify anonfun methods in order to perform super calls.
What is happening when i see the exception ?
I have a module Server and a module Client, they both run the same code except that they have different implementation of the Engine module, which is where i define all features of my framework, my RMI system is a feature of the framework for example, and for this RMI system, absolutely no code is runned into the implementations modules.
In the Engine module, I've made a player command in my program that creates a synchronised list (of type scala.collections.mutable.ListBuffer), thus, with this command i can add some player objects to the list. for example, if i add a player to the list, it will be added in the local list of the program that executes the command, and a RMI request will be done to the other computers that hosts the list in order to make them add the same object in their list.
Now, if i enter something like player add id=7 name=testPlayer x=78 y=23, it will start to get completely weird :
First of all, this exception occurs only when the server program handles the RMI request, which is completely nonsensical because as i said, nothing is run in the implementation.
For example, if i enter the command on the server, the player will be added in it's local list, and a RMI request for the add method will be sent from the server to the client, but on the client, as it will handle the request, will not crash at all (i can spam the command, nothing breaks). So, if the server handles the RMI request, it throws me this error :
java.lang.NegativeArraySizeException: -531627648
at java.base/java.lang.Class.copyFields(Class.java:3538)
at java.base/java.lang.Class.getDeclaredFields(Class.java:2341)
at fr.linkit.engine.connection.packet.serialization.tree.ClassDescription.listAllSerialFields$1(ClassDescription.scala:45)
at fr.linkit.engine.connection.packet.serialization.tree.ClassDescription.listSerializableFields(ClassDescription.scala:52)
at fr.linkit.engine.connection.packet.serialization.tree.ClassDescription.<init>(ClassDescription.scala:23)
at fr.linkit.engine.connection.packet.serialization.tree.DefaultClassProfile.<init>(DefaultClassProfile.scala:23)
at fr.linkit.engine.connection.packet.serialization.tree.DefaultSerialContext.$anonfun$getClassProfile$1(DefaultSerialContext.scala:61)
at scala.collection.mutable.HashMap.getOrElseUpdate(HashMap.scala:454)
at fr.linkit.engine.connection.packet.serialization.tree.DefaultSerialContext.getClassProfile(DefaultSerialContext.scala:61)
at fr.linkit.engine.connection.packet.serialization.tree.DefaultNodeFinder.getClassProfile(DefaultNodeFinder.scala:49)
at fr.linkit.engine.connection.packet.serialization.tree.DefaultNodeFinder.getSerialNodeForType(DefaultNodeFinder.scala:36)
at fr.linkit.engine.connection.packet.serialization.tree.DefaultNodeFinder.getSerialNodeForRef(DefaultNodeFinder.scala:44)
at fr.linkit.engine.connection.packet.serialization.tree.DefaultNodeFinder.$anonfun$listNodes$1(DefaultNodeFinder.scala:55)
at scala.collection.immutable.List.map(List.scala:246)
at fr.linkit.engine.connection.packet.serialization.tree.DefaultNodeFinder.listNodes(DefaultNodeFinder.scala:53)
at fr.linkit.engine.connection.packet.serialization.tree.nodes.ObjectNode$ObjectSerialNode.serialize(ObjectNode.scala:58)
at fr.linkit.engine.connection.packet.serialization.tree.nodes.ArrayNode$ArraySerialNode.serializeItem$1(ArrayNode.scala:84)
at fr.linkit.engine.connection.packet.serialization.tree.nodes.ArrayNode$ArraySerialNode.$anonfun$serialize$1(ArrayNode.scala:68)
at fr.linkit.engine.connection.packet.serialization.tree.nodes.ArrayNode$ArraySerialNode.$anonfun$serialize$1$adapted(ArrayNode.scala:67)
at scala.collection.ArrayOps$.foreach$extension(ArrayOps.scala:1323)
at fr.linkit.engine.connection.packet.serialization.tree.nodes.ArrayNode$ArraySerialNode.serialize(ArrayNode.scala:67)
at fr.linkit.engine.connection.packet.serialization.tree.LengthSign$.$anonfun$of$2(LengthSign.scala:62)
at fr.linkit.engine.connection.packet.serialization.tree.LengthSign$.$anonfun$of$2$adapted(LengthSign.scala:54)
at scala.collection.immutable.List.foreach(List.scala:333)
at fr.linkit.engine.connection.packet.serialization.tree.LengthSign$.of(LengthSign.scala:54)
at fr.linkit.engine.connection.packet.serialization.tree.nodes.ObjectNode$ObjectSerialNode.serialize(ObjectNode.scala:63)
at fr.linkit.engine.connection.packet.serialization.tree.nodes.ArrayNode$ArraySerialNode.serializeItem$1(ArrayNode.scala:84)
at fr.linkit.engine.connection.packet.serialization.tree.nodes.ArrayNode$ArraySerialNode.$anonfun$serialize$1(ArrayNode.scala:68)
at fr.linkit.engine.connection.packet.serialization.tree.nodes.ArrayNode$ArraySerialNode.$anonfun$serialize$1$adapted(ArrayNode.scala:67)
at scala.collection.ArrayOps$.foreach$extension(ArrayOps.scala:1323)
at fr.linkit.engine.connection.packet.serialization.tree.nodes.ArrayNode$ArraySerialNode.serialize(ArrayNode.scala:67)
at fr.linkit.engine.connection.packet.serialization.DefaultSerializer.serialize(DefaultSerializer.scala:34)
at fr.linkit.engine.connection.packet.serialization.SimpleTransferInfo.makeSerial(SimpleTransferInfo.scala:38)
at fr.linkit.engine.connection.packet.serialization.LazyPacketSerializationResult.bytes$lzycompute(LazyPacketSerializationResult.scala:27)
at fr.linkit.engine.connection.packet.serialization.LazyPacketSerializationResult.bytes(LazyPacketSerializationResult.scala:27)
at fr.linkit.engine.connection.packet.serialization.LazyPacketSerializationResult.writableBytes$lzycompute(LazyPacketSerializationResult.scala:30)
at fr.linkit.engine.connection.packet.serialization.LazyPacketSerializationResult.writableBytes(LazyPacketSerializationResult.scala:29)
at fr.linkit.server.connection.ExternalConnectionSession.send(ExternalConnectionSession.scala:53)
at fr.linkit.server.connection.ServerExternalConnection.$anonfun$sendPacket$1(ServerExternalConnection.scala:100)
at fr.linkit.engine.local.concurrency.pool.BusyWorkerPool.$anonfun$runLater$1(BusyWorkerPool.scala:351)
at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18)
at scala.util.Try$.apply(Try.scala:210)
at fr.linkit.engine.local.concurrency.pool.BusyWorkerPool.$anonfun$runLaterControl$1(BusyWorkerPool.scala:122)
at fr.linkit.engine.local.concurrency.SimpleAsyncTask.runTask(SimpleAsyncTask.scala:75)
at fr.linkit.engine.local.concurrency.pool.BusyWorkerThread.runTask(BusyWorkerThread.scala:67)
at fr.linkit.engine.local.concurrency.pool.BusyWorkerPool.$anonfun$runLaterControl$2(BusyWorkerPool.scala:132)
The exception occurs during the serialization of the response packet, (as we are performing a Remote Method Invocation, we have to send the return value of the method). In this case, the add method returns the instance of the list, so the packet will contains the instance of the list as a result value (sounds useless but i have to deal with this kind of situations). When the list gets serialized, it crashes here :
def listAllSerialFields(cl: Class[_]): Seq[Field] = {
if (cl == null)
return Seq.empty
val fields = cl.getDeclaredFields //Line 45, Here, the cl value is the generated class
fields
.filterNot(p => Modifier.isTransient(p.getModifiers) || Modifier.isStatic(p.getModifiers))
.tapEach(_.setAccessible(true))
.toList ++ listAllSerialFields(cl.getSuperclass)
}
Then, further in the method it crashes here :
private static Field[] copyFields(Field[] arg) {
Field[] out = new Field[arg.length]; //arg.length is -500 millions !
ReflectionFactory fact = getReflectionFactory();
for (int i = 0; i < arg.length; i++) {
out[i] = fact.copyField(arg[i]);
}
return out;
}
I suspect that it's the reflection data that causes that because, when i used the debugger to follow the thread execution, the jvm crashed when the debugger saw the referent field of the SoftReference<ReflectionData> Class.reflectionData field. But i repeat, on the client it does not crash, and my debugger can inspect the reflection data successfully.
EDIT -
If i call getDeclaredFields directly once the class get loaded (here for example):
var loader = puppetClass.getClassLoader
if (loader == null)
loader = getClass.getClassLoader //Use the Application's classloader
val classLoader = new GeneratedClassLoader(folderPath, loader, Seq(classOf[LinkitApplication].getClassLoader))
val clazz = Class.forName(wrapperClassName, false, classLoader).asInstanceOf[Class[_ <: PuppetWrapper[AnyRef]]]
println(s"CREATED CLASS ${clazz} IN THREAD = " + Thread.currentThread())
clazz.getDeclaredFields //Invoking a method in order to make the class load its reflectionData (causes fatal error if not made directly)
ClassMappings.putClass(clazz)
clazz
It will never crash or throw me the an exception, however, it still weird that i have to do that because only the server would oftenly crash, and when it crashes, it can does it in the exact same thread that have loaded the class...
This isn't really an answer to your original question, but re-iterates what was said in the comments. What you're doing is "unsafe", and the behavior is undefined. The fact that the workaround is working at all is somewhat incidental and cannot be relied upon. Maybe it works now, but in a future Java version it might fail.
The Unsafe class is going away once safe replacements exist for all of its useful capabilities. This will likely occur after the completion of the Panama project, which provides access to native memory. The VarHandle class is the replacement for direct field access, but it doesn't permit modifying final fields, and it likely never will. Such a backdoor prevents certain optimizations, and new Java features like "records" and "hidden classes" trust that final fields are really final. This behavior might apply to all classes at some point.
There's no planned safe alternative for allocating classes without a constructor, and so that's a problem too. The built-in Java serialization mechanism will have to continue using a backdoor until it's rewritten to use a different technique.
The safe technique is to generate a hidden constructor which performs deserialization and sets the final fields. It might also need dummy parameters to avoid conflicts with any other constructors. The constructor is added with an instrumentation agent which modifies serializable classes as they're loaded.
Ideally the hidden constructor should be private, but then accessing it becomes tricky. The agent should also define (or augment) a static class intializer which looks up the MethodHandle for the hidden constructor and passes it to some serialization framework layer. The private constructor will still be visible by any code which calls getDeclaredConstructors, but that's a relatively minor problem.
As for serializing the fields out in the first place, a VarHandle for each field can be passed along from the static initializer, or a private method is added which does the serialization. I think that the private method approach is better, and it just needs one MethodHandle for accessing it.
Thanks a lot for ones who tried to help me, and thanks to boneil for his answer because he made me become aware that Unsafe wasn't a great solution, but i still have to deal with it. However, i decided to answer because i just made a "discovery" with the Unsafe.allocateInstance method : When Unsafe allocates an instance, every fields of the objects are null but still neverless non detected as null by the JVM. I just had a case where i didn't knew why i got an exception in the init method of one of my allocated instances, i first started to think that it was called twice, but it turned out that i could'nt even debug the method execution with a breakpoint because it was making my JVM crash as soon as the debugger stops in the instance's method. Thus, as i could not use the debugger, i decided to use the plain old nooby printf statement, but still unable to debug as i got a NPE here :
(in java.lang.String.java)
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString(); //obj is null.
}
as you can see, the obj was null as it threw a NPE, but it still has been considerated as a normal instance. Therefore, by seeing this, i decided to use reflection to set the field that caused this issue as null (field.set(instance, null)), and i was able to print the entire object, and i was able to use the debugger ! So this means that it's an Unsafe thing that it does not even set fields' value to null, which is very anoying but, it's ok...
Now i think that my jvm crashed because as the debugger tried to introspect my allocated object, it received an NPE, even if it certainly check if the object was not null, thus, this made an internal error in the debugger, and then the JVM crashed.
EDIT: it seems like it's not just when memory is not initialised by Unsafe, "cursed null" fields looks to appear when Unsafe touches an object (putInt, putObject...). If an Unsafe method is invoked to put something in an object's memory, any null field of the object have a (high) chance to become a weird null field

How to fix ClassNotLoaded exception Java [duplicate]

So I'm (remotely) debugging a java/jboss application in Eclipse, stepping through line by line. At one point, an array of GridSquare objects (GridSquare is a fairly simple, standalone class, contains a few properties and methods) is created by a method call, i.e:
GridSquare[] squares = this.theGrid.getSquares(14, 18, 220, 222);
...While when I actually execute the code, the squares array does get populated with GridSquare objects, I get something odd when stepping through the code and debugging. At a breakpoint on the line immediately following the assignment shown above, if I try to view the squares array, instead of a value I get this:
org.eclipse.debug.core.DebugException: com.sun.jdi.ClassNotLoadedException: Type has not been loaded occurred while retrieving component type of array.
...Anyone know what that's about?
Basically it means the class loader has not loaded the GridSquare[] class. That being said it sounds like a bug in the debugger in some way. The breakpoint association with the code seems to be slightly broken. Either you need to recompile to get the line numbers in sync or some other issue is going on. At that point in the code (after the assignment) it needs to be loaded. Unless getSquares actually returns a subclass (GridSquareSubclass[]) at which point the JVM may not have loaded it because it doesn't need it (yet).
I ran into this error because I was running a unit test on code that uses reflection. I had made a special class for testing all the features of the code. Junit apparently uses a separate classloader for test classes (which makes perfect sense) so my code was not able to use reflection on that class. The stack trace I got was extremely generic (java.lang.InstantiationException) but when I checked in debug mode there was more detail on the Exception object itself (org.eclipse.debug.core.DebugException: com.sun.jdi.ClassNotLoadedException) which led me to this conclusion.
So I moved the special class to the main classloader (by moving the file from src/test/java to src/main/java) and it worked fine. I don't like this solution but I cannot figure out an alternative. In my case it's not a big deal but I can see how this might be a concern for others.
I have seen this happen in Eclipse when you have a subclass's class variables hiding a parent class's variables. Somehow that confuses Eclipse (and generally is a bad idea anyway :). For example:
class A {
private String a;
}
class B extends A {
public String a;
}
//Give a SIZE to the array:
GridSquare[] squares = GridSquare[this.theGrid.size()];
//Fill each element of the array with the object constructor to avoid the null value
for(int i=0; i<this.theGrid.size(); i++){
squares[i] = new GridSquare();
squares[i] = this.theGrid.getSquares(14, 18, 220, 222);
}
By initializing GridSquare will solve the problem.
squares =new GridSquare();
I faced the same problem, i just created a public static void main method, created object of same type and Run As java Application, i then removed main method, it now works fine.

The value of the local variable chaine2 is not used

I got this error message: The value of the local variable chaine2 is not used.
The code:
package com.example.Projet_java;
public class MyFirstClass
{
public static void main(String[] args) {
{ String chaine = new String("HELLO"),
chaine2 = new String();
chaine2 = chaine.toLowerCase();
}
}
}
I tried to follow the following thread
Java error "Value of local variable is not used"
but without success.
Anybody knows how I could fix it?
chaine2 = new String() is redundant. Delete that.
You should use the value of chaine2, which currently you don't. For example, print it out.
It's the chaine2 = new String(); You're assigning a new String() to chaine2, and then immediately discarding it when you reassign it in the next line with chaine2 = chaine.toLowerCase();.
Learning a specific language, even at the beginning, should not make one programmer forget to carefully design its algorithm. Your algorithm should always be the most optimal as possible.
Moderns IDE help to not forget ;) => A useless variable? (since in your case, chaine2 is not used at all after its initialization) => trash it!
Therefore, you should really take care about any warnings throwing by your favorite IDE (or other sources), even for a simple "Hello World" algorithm.
The value of the local variable chaine2 is not used is a warning and not an error.
Your IDE is saying that you never use the variable chaine2, that is, you neither use it in other operations, nor store it anywhere, nor print it on screen nor anything... Anyway your code will run!
Despite of what is being said in other answers, warnings are very useful notifications about things that may lead to errors, so they're very useful while programming, because your IDE will notice issues that you may not notice. So you shouldn't discard them while learning Java!
EDIT: If what you want to do is to get the String "HELLO" in lowercase, don't seek anymore... you got it! The only point is that you have it stored in a avariable chaine2 but you don't do anything with it...
Just do:
System.out.println("Printing chaine2: " + chaine2);
And you will see the result printed on the console.
You are setting an object to chaine2,
chaine2 = new String();
but you overwrite it at the next line, so the previously created empty String is not used for anything.
chaine2 = chaine.toLowerCase();
The compiler finds it odd, since the first line is useless, and warns you in case it is a logic error (although it is a correct program and will compile and run correctly).
It's a warning, not an error. This is the way compiler informs you thay you create variable which you never use. This variable is useless, so there is no point in creating it. You can just ignore this warning if you're learning Java, because it doesn't prevent your code to being compiled and execute. It's just a tip for you: "Hey, you have a variable you don'tuse! Maybe you've missed something?"

What can cause IllegalMonitorStateException from inside a synchronized block?

We hit an extremely surprising exception today. Inside of a synchronized block, we call wait() and it throws IllegalMonitorStateException. What can cause this?
This is happening in well-tested open source code:
http://svn.apache.org/viewvc/river/jtsk/trunk/src/com/sun/jini/jeri/internal/mux/Mux.java?view=markup#l222
We eliminated the obvious causes:
are we synchronized on the right variable? Yes, it's muxLock
is it a mutable variable? No, muxLock is final
are we using any weird "-XX:" JVM flags that might affect monitor behavior? No, but we are launching the JVM embedded inside a C++ app via JNI.
is this a strange JVM? No, it's Sun's 1.6.0_25 win/x64 JRE
is this a known JVM bug? Can't find anything relevant at http://bugs.sun.com/bugdatabase
So, I'm trying to think of more far-fetched explanations.
could an uncaught out-of-memory error cause the monitor state to be screwed up? We're looking at this, but we're seeing no evidence of memory errors yet.
UPDATE: (based on comment)
I've also verified from the stacktrace and breakpoint that the thread is indeed inside the synchronized block when the exception is thrown. It's not the case that some other unrelated code is emitting the exception (unless something is REALLY confusing Eclipse!)
The only suspicious thing I see that you are passing a reference to 'this' to some other object in your constructor. Is it possible (in fact, not unlikely) that, through weird re-ordering of things, if some other thread gets that reference to 'this' and calls the method that uses the muxlock, things can go extremely wrong.
The Java Language Specification is pretty specific about this:
An object is considered to be completely initialized when its constructor finishes. A thread that can only see a reference to an object after that object has been completely initialized is guaranteed to see the correctly initialized values for that object's final fields.
In other words, if another thread gets hold of the 'this' reference before the constructor is finished, the final field 'muxlock' might not be correctly initialized yet. In general, publishing a reference to 'this' before the constructor has finished can be pretty dangerous, especially in threaded situations.
Some potentially useful discussion about such things:
http://madpropellerhead.com/random/20100328-java-final-fields-are-not-as-final-as-you-may-think
For some older, but still useful general discussion of why publishing 'this' in a constructor is a very bad idea in general, see for instance:
http://www.ibm.com/developerworks/java/library/j-jtp0618/index.html
http://svn.apache.org/viewvc/river/jtsk/trunk/src/com/sun/jini/jeri/internal/mux/Mux.java?r1=1069292&r2=1135026&diff_format=h
here i can see that timeout was added lately
make sure that startTimeout is > than 0 otherwise you will wait(0) or wait(-n) this probably cause IllegalMonitorStateException
EDIT: Ok above is a disaster But lets try this :
we are in Mux constructor : http://svn.apache.org/viewvc/river/jtsk/trunk/src/com/sun/jini/jeri/internal/mux/Mux.java?view=markup
line 176 we create SocketChannelConnectionIO andd pass this after that we break and and different thread takes over .
in constructor of SocketChannelConnectionIO defined here : http://svn.apache.org/viewvc/river/jtsk/trunk/src/com/sun/jini/jeri/internal/mux/SocketChannelConnectionIO.java?view=markup
line 112 we register to channel with the new handler().
handler recieaves something on chanel and function let say function handleReadReady is executed we synchronize on muxLock .
now we are still in constructor so object in final is still mutable !!!
let assume it changes , now we have something waiting on different muxLock
One in a million scenario
EDIT
http://svn.apache.org/viewvc/river/jtsk/trunk/src/com/sun/jini/jeri/internal/mux/Mux.java?revision=1135026&view=co
Mux(SocketChannel channel,
int role, int initialInboundRation, int maxFragmentSize)
throws IOException
{
this.role = role;
if ((initialInboundRation & ~0x00FFFF00) != 0) {
throw new IllegalArgumentException(
"illegal initial inbound ration: " +
toHexString(initialInboundRation));
}
this.initialInboundRation = initialInboundRation;
this.maxFragmentSize = maxFragmentSize;
//LINE BELOW IS CAUSING PROBLEM it passes this to SocketChannelConnectionIO
this.connectionIO = new SocketChannelConnectionIO(this, channel);
//Lets assume it stops here we are still in constructor
//and we are not in synchronized block
directBuffersUseful = true;
}
now in constructor of SocketChannelConnectionIO
http://svn.apache.org/viewvc/river/jtsk/trunk/src/com/sun/jini/jeri/internal/mux/SocketChannelConnectionIO.java?revision=1069292&view=co
SocketChannelConnectionIO(Mux mux, SocketChannel channel)
throws IOException
{
super(mux);
channel.configureBlocking(false);
this.channel = channel;
//Line below we are registering to the channel with mux that is still mutable
//this is the line that actually is causing the problem move that to
// start() and it should work
key = selectionManager.register(channel, new Handler());
}
move this code to start() should work key = selectionManager.register(channel, new Handler()); (i am assuming start is executet when we want to start prosessing)
/**
* Starts processing connection data.
*/
void start() throws IOException {
key = selectionManager.register(channel, new Handler());
key.renewInterestMask(SelectionKey.OP_READ);
}
But it would be much better not to create SocketChannelConnectionIO in the constructor of mux but maybe somewhere after that the same for second constructor creating StreamConnectionIO with this
The answer is in my opinion that its either a bug, or someone changed the object behind the reference despite its being final. If you can reproduce it, I recommend to set a read/write breakpoint on muxlock field to see if it is touched or not. You could check the identityhashcode of the muxlock in the first line of the synchronized block, and before waits and notifies with appropiate log entries or breakpoints. With reflection you can change final references. Quote from http://download.oracle.com/javase/6/docs/api/java/lang/reflect/Field.html:
"If the underlying field is final, the method throws an IllegalAccessException unless setAccessible(true) has succeeded for this field and this field is non-static. Setting a final field in this way is meaningful only during deserialization or reconstruction of instances of classes with blank final fields, before they are made available for access by other parts of a program. Use in any other context may have unpredictable effects, including cases in which other parts of a program continue to use the original value of this field."
Maybe its a bug in eclispe, and during debugging it somehow changes the field. Is it reproducable outside eclispe as well? Put a printstractrace in catch and see what happens.
Member variables are not as final as one would hope to. You should put the synchronized object into a final local variable, first. This does not explain why the member variable is altered, but if it fixes the problem you at least know that the member variable is really modified.

Debugging stack data not assigned to a named variable

Is there a way to view stack elements like un-assigned return values or exceptions that not assigned to a local variable? (e.g. throw new ...)
For example, suppose I have code along the lines of:
public String foo(InputStream in) throws IOException {
NastyObj obj = null;
try {
obj = new NastyObj(in);
return (obj.read());
} finally {
if (obj != null) obj.close();
}
}
Is there any way to view the return or exception value without stepping to a higher level frame where it is assigned? This is particularly relevant with exceptions because you often have to step back up through a number of frames to find an actual handler.
I usually use the Eclipse debugging environment, but any answer is appreciated. Also, if this cannot be done, can you explain why? (JVM, JPDA limitation?)
The answer seems to be that both JPDA/JDI and Eclipse are deficient.
I’ve verified the following, but I’m not going to bother posting the code unless someone really needs it.
For the most part, JDI mirrors the structure of the code. Named locals for a given scope can be obtained through the debuggee thread’s current StackFrame. Unscoped locals and method arguments can be obtained through the debuggee thread’s current Method. However, in general where the documentation refers to a LocalVariable, it is a named local.
It IS possible to get the return value of a function, if the function is returning normally and you are using a 1.6 debugging setup (RFE). If the debugger listens for MethodExitEvent, then event.returnValue() gets the value returned after all the method has finished executing. According to the documentation, this event is NOT generated when a method terminates via a thrown exception.
The conclusion is that if you use JDI directly under Java 1.6, you can get the return value of a function before it's assigned to a local, if it returns normally. The Eclipse and Netbeans UIs don't support this. You can't get information about Exceptions that have been thrown but not caught yet.
Couldn't you just catch the IOException (and name it) and then rethrow it? (Don't know Java, but that's what I'd do in C++ and Python.) Of course, this answer is invalid if you can't edit the given code or are inspecting the state right now and need to know what it looks like... But if you can edit the code, that seems like the way to go.

Categories