Недавно младший разработчик прислал мне пропусковую стопку и был довольно удивлен, когда я мгновенно знал проблему и указывал ему на необходимое изменение. Чтобы быть справедливым, у меня было преимущество того, чтобы быть человеком, который поставил эту ошибку там в первую очередь … но до сих пор способность Glan Glan Inform от трассировки стека, даже упущенного, является серьезным навыком.
Рассматриваемый след стека был ClassnotfoundException
Как правило, это довольно легко и уже говорит вам все, что вам нужно знать. Класс не там. Почему это не на самом деле вопрос того, что мы сделали неправильно. В этом случае, поскольку проект был запугнут, ошибка заключалась в том, что этот класс не был исключен из запутывания.
Несмотря на все ненависть, это прошло за эти годы, Nullpointerexception
является одним из моих любимых исключений. Вы мгновенно знаете, что произошло, и в большинстве случаев стек ведет почти непосредственно к проблеме. Есть несколько краевых чехлов E.g.
myList.get(offset).invokeMethod();
Так какой сработал Nullpointerexception
?
Если вы используете последнюю версию Java, это скажет вам, что довольно круто. Но если мы все еще в Java 11 (или 8), есть более одного варианта. По крайней мере, 3 или, может быть, 4, если мы немного обманываем:
милист
это очевидный но редко это ноль И если так, вы бы увидим это немедленноСмещение может быть нулевым. Это может быть целочисленным объектом, в этом случае это может быть
null
Из-за автообкинга. Это также менее вероятноНаиболее вероятным виновником в этом конкретном случае является возвращаемой стоимость от
Получить ()
Способ, который означает один из элементов списканулевой
Наконец
invokemethod
Сам может броситьNullpointerexception
Отказ Но это немного обмана, так как стек будет немного глубже
Поэтому, не зная ничего о коде, мы можем в значительной степени угадать, что не удалось на линии, просто узнав тип исключения. Но это не ведет нас непосредственно к ошибке во всех случаях.
Был нуль
Что Nullpointerexception
вероятно, произошло из-за нулевого в списке. Предполагая, что вы проверили, что вы все равно не знаете, как этот нуль попал в список в первую очередь …
Это не сложно выяснить, давайте предположим, что список имеет ArrayList
Тип, в этом случае просто откройте ArrayList
Класс (который вы можете сделать с помощью Control-O в Intellij) и поместите условный точку останова на Добавить ()
метод. Вы можете проверить, если значение NULL, и это остановится на точке останова, если кто-то пытается добавить нуль в список.
Теперь это не поймает все случаи null
подкрадывается в список. Это может сделать это через API по потоку, через Addall ()
и пара других методов. Приятно в том, что мы можем схватить в значительной степени любой из этих методов:
С Addall ()
принимает Коллекция
Мы можем использовать стандарт Содержит ()
Метод проверки, если у нас есть null
элемент в Коллекция
И если так остановиться.
Что если это «иногда» хорошо?
Поэтому мы запускаем этот код и Bingo он останавливается на точке останова … Но, к сожалению, это не правильный случай. Эта точка останова связана с другим списком, который мы не отладки прямо сейчас. Видимо в этом списке A null
Значение в порядке и ожидается.
Итак, мы нажимаем «Продолжение», и точка останова снова и снова попадает. Каждый раз для неправильного списка … Это часто точка, в которой разработчики громко прокляты и ругаются от отладки для старых старых журналов.
Так что вокруг этой проблемы существует несколько способов. Самый идеальный — избежать этого конкретного списка. Если у вас есть способ узнать этот список E.g. Глобальный экземпляр или первый элемент могут быть конкретным значением, которое вы можете просто увеличить исходную условную точку останова E.G. В этом случае мы предполагаем первый элемент в null
в порядке в порядке 77, в этом случае это условие будет обработать проблему:
Это не идеально, но работает вокруг проблемы, предполагая, что она достаточно локализована.
Вложенные следы стека
Так что это одна из «болей» в современных каркасах. Рамки ловит исключение и распространяет его, упаковывая его в свое исключение. Промыть повторять. Вы в конечном итоге с кукла матрешки от следов стека.
Просит все эти стеки и нахождение того, что имеет значение, часто бывает огромной частью боли. Особенно в рамках, таких как весна, где прокси-код делает стеки особенно долго и трудно читать.
Например.:
javax.ws.rs.ProcessingException: RESTEASY004655: Unable to invoke request: org.apache.http.conn.HttpHostConnectException: Connect to localhost:8443 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Connection refused (Connection refused) at org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine.invoke(ApacheHttpClient4Engine.java:328) at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.invoke(ClientInvocation.java:443) at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invokeSync(ClientInvoker.java:149) at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invoke(ClientInvoker.java:112) at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientProxy.invoke(ClientProxy.java:76) at com.sun.proxy.$Proxy307.grantToken(Unknown Source) at org.keycloak.admin.client.token.TokenManager.grantToken(TokenManager.java:90) at org.keycloak.admin.client.token.TokenManager.getAccessToken(TokenManager.java:70) at org.keycloak.admin.client.token.TokenManager.getAccessTokenString(TokenManager.java:65) at org.keycloak.admin.client.resource.BearerAuthFilter.filter(BearerAuthFilter.java:52) at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.filterRequest(ClientInvocation.java:579) at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.invoke(ClientInvocation.java:440) at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invokeSync(ClientInvoker.java:149) at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invoke(ClientInvoker.java:112) at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientProxy.invoke(ClientProxy.java:76) at com.sun.proxy.$Proxy315.toRepresentation(Unknown Source) at io.athena_tech.server.security.keycloak.KeycloakRealmService.lambda$doesLightrunRealmExist$0(KeycloakRealmService.java:124) at io.athena_tech.server.security.keycloak.KeycloakApi.getWithAdmin(KeycloakApi.java:35) at io.athena_tech.server.security.keycloak.KeycloakRealmService.doesLightrunRealmExist(KeycloakRealmService.java:122) at io.athena_tech.server.security.keycloak.KeycloakRealmService$$FastClassBySpringCGLIB$$9e16800d.invoke() at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:366) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691) at io.athena_tech.server.security.keycloak.KeycloakRealmService$$EnhancerBySpringCGLIB$$7eca0d51.doesLightrunRealmExist( ) at io.athena_tech.server.service.client.InitKeycloakService.initDefaultCompanies(InitKeycloakService.java:146) at io.athena_tech.server.service.client.InitKeycloakService$$FastClassBySpringCGLIB$$35f06991.invoke( ) at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:62) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691) at io.athena_tech.server.service.client.InitKeycloakService$$EnhancerBySpringCGLIB$$5ae1a459.initDefaultCompanies( ) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at org.springframework.context.event.ApplicationListenerMethodAdapter.doInvoke(ApplicationListenerMethodAdapter.java:305) at org.springframework.context.event.ApplicationListenerMethodAdapter.processEvent(ApplicationListenerMethodAdapter.java:190) at org.springframework.context.event.ApplicationListenerMethodAdapter.onApplicationEvent(ApplicationListenerMethodAdapter.java:153) at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172) at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165) at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139) at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:403) at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:360) at org.springframework.boot.context.event.EventPublishingRunListener.running(EventPublishingRunListener.java:103) at org.springframework.boot.SpringApplicationRunListeners.running(SpringApplicationRunListeners.java:77) at org.springframework.boot.SpringApplication.run(SpringApplication.java:330) at io.athena_tech.server.AthenaServerApp.main(AthenaServerApp.java:64) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) Caused by: org.apache.http.conn.HttpHostConnectException: Connect to localhost:8443 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Connection refused (Connection refused) at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:156) at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:376) at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:393) at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236) at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186) at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89) at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185) at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83) at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56) at org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine.invoke(ApacheHttpClient4Engine.java:323) ... 64 common frames omitted Caused by: java.net.ConnectException: Connection refused (Connection refused) at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:399) at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:242) at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:224) at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:403) at java.base/java.net.Socket.connect(Socket.java:609) at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:368) at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142) ... 74 common frames omitted
Может кто-нибудь сказать мне, что я сделал неправильно, когда пытаясь запустить наш сервер локально …
Давайте попробуем сломать его, начиная с наименьшего исключения, которое обычно является корневой причиной:
Caused by: java.net.ConnectException: Connection refused (Connection refused) at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:399) at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:242) at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:224) at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:403) at java.base/java.net.Socket.connect(Socket.java:609) at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:368) at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
Есть проблема подключения. Соединение отказывается от, что означает, что наш сервер пытается подключиться к другому серверу, но он не может.
Так что это дало нам какую-то основную информацию, но больше ничего.
Давайте продолжим одно исключение вверх и посмотрите на второй блок. Так как это большой, я сосредощучу только на краю исключения:
Caused by: org.apache.http.conn.HttpHostConnectException: Connect to localhost:8443 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Connection refused (Connection refused) at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:156) at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:376)
Опять ничего здесь. Это код подключения Apache. Но Нет информации о том, кто вызвал ее или почему.
Таким образом, мы вернемся до вершины, что менее типично, и здесь мы можем найти ответ:
javax.ws.rs.ProcessingException: RESTEASY004655: Unable to invoke request: org.apache.http.conn.HttpHostConnectException: Connect to localhost:8443 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Connection refused (Connection refused) at org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine.invoke(ApacheHttpClient4Engine.java:328) at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.invoke(ClientInvocation.java:443) at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invokeSync(ClientInvoker.java:149) at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invoke(ClientInvoker.java:112) at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientProxy.invoke(ClientProxy.java:76) at com.sun.proxy.$Proxy307.grantToken(Unknown Source) at org.keycloak.admin.client.token.TokenManager.grantToken(TokenManager.java:90) at org.keycloak.admin.client.token.TokenManager.getAccessToken(TokenManager.java:70) at org.keycloak.admin.client.token.TokenManager.getAccessTokenString(TokenManager.java:65) at org.keycloak.admin.client.resource.BearerAuthFilter.filter(BearerAuthFilter.java:52)
Если вы будете выглядеть немного ниже, вы увидите org.keycloak
пакеты. Это по сути означает, что я забыл запустить KeyCloak перед запуском сервера. Это было хорошо скрыто в этом стеке и требовало много доменных знаний (мы используем KeyCloak), чтобы понять это.
Это отстой. Если бы я был новым в команде, пытаясь запускать вещи, чтобы запустить (то есть именно тогда, когда произойдет такой исключение), я бы был сбит с толку исключением. По крайней мере, это взяло бы мне некоторое время, чтобы понять это. К сожалению, у меня нет серебряной пули для этой конкретной проблемы.
Просто продолжайте читать стек, ответ обычно находится в крае (нижней или верхней части). Не сдавайся, если что-то не будет мгновенно.
TL; доктор
Во многих случаях мы можем пожелать причиной исключения, которую мы видим в журнале или получите от пользователя, просто просмотрев трассировку стека и копаться глубже. Очевидно, Имейте в виду вложенные исключения и другие такие проблемы.
Отладчик все еще может быть отличным союзником при попытке выяснить корневую причину стека исключения. Мы можем использовать функции, такие как условные точки останова, чтобы сузить это вниз. Удивительно, что мы не трогали на точку зрения исключения в этом посте. Я думаю, что у них есть ценность Но когда у нас есть стек, мы уже знаем (примерно) Что произошло и где.
Нам нужно что-то, что выходит за пределы этого, и я пытался охватить это в этой статье.
Оригинал: «https://dev.to/codenameone/understanding-stack-traces-and-debugging-them-further-mif»