当尝试执行某些Kotlin代码时,同时也使用JUnit,Intellij IDEA将执行代码直到结束,而不是在断点处停止。
演示:
class Tester {
@Test
fun shouldBreakpoint() {
//Line where threads should suspend:
println("Should Suspend Here") //Breakpoint added to this line
println("Shouldn't run this code unless I release above breakpoint")
}
}
单击“Debug Tester”或“Debug shouldBreakpoint”时,没有断点可以正常工作。
控制台输出两条打印线,而不会在断点处停止。如果使用Java编写相同的代码,调试器将起作用:
public class Testerino {
@Test
public void shouldBreakpoint() {
System.out.println("Should Suspend Here"); //Breakpoint added to this line
System.out.println("Shouldn't run this code unless I release above breakpoint");
}
}
在Kotlin main
函数上运行时,它也能正常工作:
fun main(args: Array<String>) {
println("Should Suspend Here") //Breakpoint added to this line
println("Shouldn't run this code unless I release above breakpoint")
}
这是在Android项目上运行,build.gradle(app)文件是:
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
android {
compileSdkVersion 27
buildToolsVersion "27.0.3"
defaultConfig {
applicationId "me.kerooker.visualhonk"
minSdkVersion 19
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
}
buildTypes {
release {
minifyEnabled false
shrinkResources false
proguardFiles getDefaultProguardFile('proguard-android.txt')
}
debug {
debuggable true
minifyEnabled false // set this to false
proguardFiles getDefaultProguardFile('proguard-android.txt')
}
}
}
configurations.all {
resolutionStrategy {
forcedModules = [
"org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version",
"org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
]
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:27.+'
compile 'com.android.support.constraint:constraint-layout:+'
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
testCompile 'io.kotlintest:kotlintest:2.0.7'
testCompile 'junit:junit:4.12'
}
repositories {
mavenCentral()
}
Intellij可以做些什么来正确识别并在断点处停止?
答案 0 :(得分:1)
从this commit开始,此错误似乎已修复。更新Intellij以获取新版本。
如果您无法更新,则解决方法是从运行过程中删除gradle aware make ,并且只在您进行更改时构建代码(而不是每次启动时都是如此)调试)
修复说明:
Hitting breakpoints in Kotlin JUnit test with an Android Gradle
project sometimes(*) does not work in Android Studio 3.1 beta.
(*) The issue is related to various threads running concurrently
with "dumb" mode background code, so the issue reproduces only
on certain configurations.
In a nutshell, the issue is as follows
* On one hand, gradle build finishes, fires an event ("buildFinished")
that is processed "later" and that causes the IDE to enter "dumb" mode
for a shot amount of time (about 300-500 msec on a somewhat up to date
multi-core computer).
* On the other hand, once the JVM of the debuggee is started, breakpoints
need to be resolved (on the debugger thread, through a call to
com.intellij.debugger.engine.CompoundPositionManager.createPrepareRequests.
This code calls into the "KotlinPositionManager.createPrepareRequests",
which in turns calls into "PerFileAnalysisCache.analyze". That method
returns "AnalysisResult.EMPTY" is the project is in dumb mode.
This return value prevents callers from successfully resolving
the source location into a breakpoint.
Given that the 2 code paths above execute on separate threads without
explicit synchronization, the "failed to resolve breakpoint" issue
occurs sporadically, to the point it happens 100% of the time on
certain configuration.
The fix is so wrap the kotlin breakpoint resolution code inside
a "runReadActionInSmartMode" so that the debugger thread "waits"
for "dumb" mode to terminates before trying to resolve breakpoint
locations.