chenggwang commented on PR #671: URL: https://github.com/apache/tomcat/pull/671#issuecomment-1762749332
> The benefit seems null IMO, in the debugger it will print out that this is null instead of a NPE, which should mean the same for a developer. Also, Nio2Channel.toString is the same. Following is the`NioChannel` attribute `SocketChannel sc`, along with its `constructor`, `rest` methods and `toString` method.We initialize a `NioChannel` through the constructor, only the `bufHandler` property is assigned a value, and its `sc` property remains null. At this point the object is nearly created, meaning we can use its properties and methods as we wish. But when we use its toString() method, `super.toString() + ":" + sc.toString()`, `sc` is null, so it throws an NPE. The `sc` is not assigned a value until we call the reset method. Otherwise, sc.toString() throws NPE directly instead of printing null ```java public class NioChannel implements ByteChannel, ScatteringByteChannel, GatheringByteChannel { ... Omit extraneous code protected final SocketBufferHandler bufHandler; protected SocketChannel sc = null; protected NioSocketWrapper socketWrapper = null; public NioChannel(SocketBufferHandler bufHandler) { this.bufHandler = bufHandler; } ... public String toString() { return super.toString() + ":" + sc.toString(); } public void reset(SocketChannel channel, NioSocketWrapper socketWrapper) throws IOException { this.sc = channel; this.socketWrapper = socketWrapper; bufHandler.reset(); } ...Omit extraneous code } ``` Going back to the object-oriented level, when we provide an object, we need to make sure that the basic functionality it provides to the outside world after initialization is complete is usable and reliable. The basic functionality of course includes the `toString()` method, because this is its calling card, through which the outside world should know the basic information about the object. This is also the original purpose of the toString method. On line 12 we create a channel with `createChannel(bufhandler)`,At this point we are calling the constructor of the NioChannel.This is the same explanation as I started with, sc is still null and all calls to channel's` toString` method before line 14 report NPE. Similarly `NioSocketWrapper newWrapper`, the `newWrapper.toString()` method throws an NPE until the rest method is called, as it looks like this `super.toString() + ":" + String.valueOf(socket)`, ` String.valueOf(socket)` still calls socket(NioChannel)'s `sc.toString`, when `sc` is null. ```java line 1 protected boolean setSocketOptions(SocketChannel socket) { line 2 NioSocketWrapper socketWrapper = null; line 3 try { // Allocate channel and wrapper line 4 NioChannel channel = null; line 5 if (nioChannels != null) { line 6 channel = nioChannels.pop(); } line 7 if (channel == null) { line 8 SocketBufferHandler bufhandler = new SocketBufferHandler( line 9 socketProperties.getAppReadBufSize(), line 10 socketProperties.getAppWriteBufSize(), line 11 socketProperties.getDirectBuffer()); line 12 channel = createChannel(bufhandler); } line 13 NioSocketWrapper newWrapper = new NioSocketWrapper(channel, this); line 14 channel.reset(socket, newWrapper); line 15 connections.put(socket, newWrapper); line 16 socketWrapper = newWrapper; ``` createChannel method ```java protected NioChannel createChannel(SocketBufferHandler buffer) { if (isSSLEnabled()) { return new SecureNioChannel(buffer, this); } return new NioChannel(buffer); } public NioChannel(SocketBufferHandler bufHandler) { this.bufHandler = bufHandler; } ``` <img width="709" alt="屏幕截图 2023-10-14 163405" src="https://github.com/apache/tomcat/assets/90715678/44871f56-e5a2-435e-86cf-e15063806971"> Above is the `System.out.println` I added between line 13 and 14 to output the `channel` and `newWrapper` objects, throwing NPE's.I have a monitoring project that tracks changes in the life cycle of an object after any object is created, we are monitoring all constructors, reflections, and start logging as soon as an object is created. The two lines `System.out.println` in the diagram are similar to the abstraction of our monitoring function as a buried point. To clarify our buried points are at the bytecode level, there is no hardcoding of tomcat source code dumping. However, the NPE occurred when logging, so I went down to the source code to debug it, and found that it was the reason that toString() didn't judge the null. The `toString` method doesn't seem to have much use or impact on the application itself, but it's still useful for monitoring and logging. So if tomcat side does not change, I can only in my monitoring project to make a patch to find NioChannel, wait for the rest method to execute and then track the channel object, haha but I feel that my code is very ugly! Still hope that the official side of the adjustment, I submit also PR also found a lot of toString method with "+" splicing, high version of the jdk compilation will automatically StringBuilder, so did not change the + sign. Here judgment empty for tomcat performance is almost no consumption! -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org