Java 了解Android紧循环/自旋挂起错误

Java 了解Android紧循环/自旋挂起错误,java,android,loops,dalvik,Java,Android,Loops,Dalvik,我正在android上开发一款游戏“太空RPG”——目前只有在大多数Galaxy S4和HTC上才会出现这个错误。这都是Java 游戏将暂停,当我尝试调试进程并挂起有问题的线程时,它不会挂起,并且会发生一个自旋挂起错误。 线程转储让我看到它在一个特定的while循环中,该循环获取一个期望的“结束位置”,并以不断增加的距离步向后迭代以找到一个“开始位置” 这就是事情变得烦人的地方。我可以验证循环不能无限期地运行,即使条件是while(true),在调用中断之前,循环不可能运行超过200次迭代(这个

我正在android上开发一款游戏“太空RPG”——目前只有在大多数Galaxy S4和HTC上才会出现这个错误。这都是Java

游戏将暂停,当我尝试调试进程并挂起有问题的线程时,它不会挂起,并且会发生一个自旋挂起错误。 线程转储让我看到它在一个特定的while循环中,该循环获取一个期望的“结束位置”,并以不断增加的距离步向后迭代以找到一个“开始位置”

这就是事情变得烦人的地方。我可以验证循环不能无限期地运行,即使条件是while(true),在调用中断之前,循环不可能运行超过200次迭代(这个断言由我尝试过的其他每部手机上的代码进行备份)

为了缓解我对这个问题的担忧,我在循环中添加了一个简单的递增变量,如果它超过1000,它将注销一些内容,这样我就可以看到它确实运行了太多次,以防某个变量设置不正确或什么的。 当此计数器代码存在时,不会发生崩溃/挂起。我也没有看到任何日志显示它运行了1000次以上。

如果我移除这个计数器,每次播放5-10秒后都会出现挂起(while循环可能会运行10次,尽管这会有所不同)

因此,我的问题是,到底发生了什么P 为什么这些较新的手机(但似乎没有一款较旧的手机)在没有递增变量的情况下,会出现一个循环的问题,该循环正在进行有效的工作并且不会持续很长时间。线程如何可能在该循环中暂停,以及使用额外的计数器变量如何解决该问题? 这项工作是在opengl渲染线程上完成的,如果这很重要的话

我在大多数S4上都有这样的报道,但至少有一个S4没有发生。我今天用的那个正在发生。这让我想知道它是否可能与特定的android、java、dalvik或手机上的其他东西有关,但不幸的是,我没有任何关于它工作的S4的细节

任何帮助、指导、想法或进一步阅读此类内容都将不胜感激,非常感谢

float vel = 1.0f; // final velocity is 1. We are working backwards to find out what the starting velocity will need to be.
int i = 0;
double xmath = Math.sin(rot* (Math.PI/180.0f)); // component of velocity for x,y direction based on rotation
double ymath =  Math.cos(rot* (Math.PI/180.0f));
while (true) {
        /* with this section uncommented, the stall never happens...
         ++i;
        if (i>1000) {
            // Something went rather wrong
            vel = 91.0f; // LOG WAS HERE, now has a fallback value justincase
            break;
        }
        */
        vel *= 1.2f;            
        dx -= vel* xmath;
        dy += vel* ymath;           
        if (distance < (float)Math.sqrt(dx*dx+dy*dy)) {
            break;
        }
}
// Give the ship a velocity that is appropriate for the distance remaining
_AI.Ship.Velocity = vel;
float-vel=1.0f;//最终速度为1。我们正在反向工作,以找出需要的起始速度。
int i=0;
double xmath=Math.sin(rot*(Math.PI/180.0f));//基于旋转的x、y方向的速度分量
double-ymath=Math.cos(rot*(Math.PI/180.0f));
while(true){
/*此部分未注释时,暂停不会发生。。。
++一,;
如果(i>1000){
//出了点问题
vel=91.0f;//日志在此,现在具有回退值
打破
}
*/
水平*=1.2f;
dx-=vel*xmath;
dy+=vel*ymath;
if(距离<(浮点)数学sqrt(dx*dx+dy*dy)){
打破
}
}
//给船一个适合剩余距离的速度
_AI.Ship.Velocity=vel;
这可能是

bug有完整的细节;简而言之:一些供应商似乎使用了Dalvik VM的修改版本。对JIT编译器所做的更改可防止在某些情况下发生线程挂起

本期的试金石测试是将标准零售设备与GS4和HTC1的“纯Android”进行比较。如果前者显示出不正常的行为,但后者工作正常,那么您可能会看到特定于供应商的问题


解决方法是做你已经做过的事情:降低代码的效率,这样就不会陷入“优化”的情况。理想情况下,应用程序会在运行时为没有问题的设备选择不同的代码路径,但我不知道在运行时检测问题的好方法。

你能展示一些代码吗?完成,如果有帮助的话…?我想你可以明确排除线程问题,比如死锁或类似的问题。但话说回来,如果这是一个僵局,它应该发生在更多的全新手机上。。。困难的一个。Dalvik线程在到达安全点时会自动挂起。Spin-on-suspend意味着线程没有到达安全点,因此(a)您的循环没有退出,(b)VM中的某些内容出错。你在logcat中看到类似“JIT unchain all”的东西了吗?我最初的猜测是,JIT从紧循环中剥离了挂起检查,这是允许的——另一个线程可以“取消”段以重新引入检查——但有些地方工作不正常。你看到运行stock Android的GS4/HTC1上的问题了吗,与零售版三星/HTC相比,android本机代码是否也会出现这种情况,抽象出导致这种情况的软件是哪一部分?这是我知道的唯一原因
ffmpeg
(静态二进制自定义编译,n2.0.1 tag mint作为克隆)在某些设备上失败,而在其他设备上没有失败(但在通过
valgrind
启动时没有任何设备失败!!我现在假设,经常陷阱内部程序)本机代码是用gcc编译的,它完全独立于Dalvik内部的JIT编译器。