在Javascript中播种随机数生成器

时间:2009-02-06 17:37:40

标签: javascript random

是否可以在Javascript中播种随机数生成器(Math.random)?

16 个答案:

答案 0 :(得分:165)

不,它不是,但是编写自己的生成器相当容易,或者更好地使用现有的生成器。退房:this related question

另见David Bau的博客more information on seeding

答案 1 :(得分:140)

注意:尽管(或者更确切地说,由于)简洁和明显的优雅,这种算法在随机性方面绝不是高质量的算法。寻找例如this answer中列出的那些更好的结果。

(最初改编自对另一个答案的评论中提出的一个聪明的想法。)

var seed = 1;
function random() {
    var x = Math.sin(seed++) * 10000;
    return x - Math.floor(x);
}

您可以将seed设置为任意数字,只需避免零(或Math.PI的任意倍数)。

在我看来,这个解决方案的优雅来自于缺少任何“神奇”数字(除了10000之外,它代表了为避免奇怪模式而必须丢弃的最小数字位数 - 请参阅值为{{的结果3}},10100)。简洁也很好。

它比Math.random()慢了一点(因子为2或3),但我相信它和用JavaScript编写的任何其他解决方案一样快。

答案 2 :(得分:62)

我在纯JavaScript中实现了许多好的,短的和快速的可复制PRNG功能。所有这些都可以播种,并提供高质量的数字。

首先,注意正确初始化PRNG。下面的大多数生成器没有内置的种子生成过程,但接受一个或多个32位值作为初始 PRNG的州。类似的种子(例如1和2的种子)可以在较弱的PRNG中引起相关,导致输出具有相似的性质(例如随机生成的水平相似)。为避免这种情况,最好使用分布均匀的种子来初始化PRNG。

值得庆幸的是,哈希函数非常适合从短字符串为PRNG生成种子。即使两个字符串相似,良好的散列函数也会产生非常不同的结果。以下是基于MurmurHash3混音功能的示例:

function xmur3(str) {
    for(var i = 0, h = 1779033703 ^ str.length; i < str.length; i++)
        h = Math.imul(h ^ str.charCodeAt(i), 3432918353),
        h = h << 13 | h >>> 19;
    return function() {
        h = Math.imul(h ^ h >>> 16, 2246822507);
        h = Math.imul(h ^ h >>> 13, 3266489909);
        return (h ^= h >>> 16) >>> 0;
    }
}

每次对return函数的后续调用都会产生一个新的&#34;随机&#34;要用作PRNG中的种子的32位散列值。以下是您可以使用它的方法:

// Create xmur3 state:
var seed = xmur3("apples");
// Output four 32-bit hashes to provide the seed for sfc32.
var rand = sfc32(seed(), seed(), seed(), seed());

// Output one 32-bit hash to provide the seed for mulberry32.
var rand = mulberry32(seed());

// Obtain sequential random numbers like so:
rand();
rand();

这当然是功能性的JS,但它可以被客观化。

向货物(发电机)前进。

SFC32

这个gem来自PractRand随机数测试套件,它可以毫无问题地通过。 PractRand据称甚至比TestU01更严格。 sfc32 具有128位状态,并且在JS中也非常快(xoshiro128 **稍快,但质量更差)。这可能是我选择的PRNG。

function sfc32(a, b, c, d) {
    return function() {
      a >>>= 0; b >>>= 0; c >>>= 0; d >>>= 0; 
      var t = (a + b) | 0;
      a = b ^ b >>> 9;
      b = c + (c << 3) | 0;
      c = (c << 21 | c >>> 11);
      d = d + 1 | 0;
      t = t + d | 0;
      c = c + t | 0;
      return (t >>> 0) / 4294967296;
    }
}

Mulberry32

Mulberry32也非常快,质量很好(作者说它通过了gjrand的所有测试)。如果你只需要一个简单但体面的 PRNG,我会推荐这个。

它具有32位的状态和2 32 的完整周期。如果你只想用一个32位整数播种并且不关心birthday problem,这是理想的选择。 Mulberry32中有43亿个可能状态,而sfc32 / xoshiro128 **则为340个未命中状态。

function mulberry32(a) {
    return function() {
      var t = a += 0x6D2B79F5;
      t = Math.imul(t ^ t >>> 15, t | 1);
      t ^= t + Math.imul(t ^ t >>> 7, t | 61);
      return ((t ^ t >>> 14) >>> 0) / 4294967296;
    }
}

xoshiro128 **

截至2018年5月, xoshiro128 ** Xorshift family的新成员。它提供128位状态,速度非常快。

function xoshiro128ss(a, b, c, d) {
    return function() {
        var t = b << 9, r = a * 5; r = (r << 7 | r >>> 25) * 9;
        c ^= a; d ^= b;
        b ^= c; a ^= d; c ^= t;
        d = d << 11 | d >>> 21;
        return (r >>> 0) / 4294967296;
    }
}

此PRNG是Blackman / Vigna的最新版本,他还编写了2015年在谷歌Chrome中使用的PRNGs xorshift128 +和xoroshiro。它是少数几款具有32位版本的现代PRNG之一。 xoroshiro64**也是一个很有前途的选择,但只有64位状态,并且很大程度上被xoshiro取代。

作者声称它很好地传递了随机性测试(albeit with caveats)。其他研究人员指出,在BigCrush中失败了一些测试(特别是LinearComp和BinaryRank)。但实际上并不重要,特别是如果将32位值转换为0-1之间的浮点数,就像这些PRNG一样。但是,如果您依赖于低位,则可能会出现问题。

JSF

这是JSF或&#39; smallprng&#39;作者:Bob Jenkins(2007),他是ISAACSpookyHash的人。它在PractRand测试中performs well并且应该非常快。假设平均周期长度为2 ^ 126但尚未正式确定&#39;。

function JSF(seed) {
    function jsf() {
        var e = s[0] - (s[1]<<27 | s[1]>>>5);
         s[0] = s[1] ^ (s[2]<<17 | s[2]>>>15),
         s[1] = s[2] + s[3],
         s[2] = s[3] + e, s[3] = s[0] + e;
        return (s[3] >>> 0) / 4294967296; // 2^32
    }
    seed >>>= 0;
    var s = [0xf1ea5eed, seed, seed, seed];
    for(var i=0;i<20;i++) jsf();
    return jsf;
}

此版本不需要单独的种子功能。但结果是,只有32位可以播种,并且该版本预先运行jsf()20次以分散初始状态,这可能是昂贵的。

如果需要,可以直接初始化整个128位状态并删除for循环。我决定保留原始构造,因为作者验证了给定配置中每个可能的32位种子的循环长度。

LCG(又名Lehmer / Park-Miller RNG或MLCG)

这只是为了提供其他答案中提到的选项的更好替代方案,例如Math.sinMath.PI方法,这些方法在不同平台上不太一致或可靠。这个LCG实现非常快,但只有31位状态,并且未能通过前面提到的生成器通过飞行颜色的一些统计测试。虽然这只是一个单行 - 但很不错:)。

var LCG=s=>()=>(2**31-1&(s=Math.imul(48271,s)))/2**31;

这是Park–Miller in 1988 & 1993提出的最小标准 RNG,并在C ++ 11中以minstd_rand实现。请记住,状态和周期仅为31位(31位给出20亿个可能状态,32位给出两倍)。这是其他人试图取代的PRNG类型。

它会工作,但我不会使用它,除非你真的需要速度并且不关心随机性质量(无论是什么是随机的?)或者31位状态/周期大小。非常适合游戏果酱或演示或其他东西。此外,LCG受种子相关影响,因此最好丢弃LCG的第一个结果

似乎还有其他乘法器可以提供完整的32位状态。我不知道这些在统计上是否比Park-Miller更好/更差,但在这里它们是为了完整性。

var LCG=s=>()=>((s=Math.imul(741103597,s))>>>0)/2**32;
var LCG=s=>()=>((s=Math.imul(1597334677,s))>>>0)/2**32;

这些乘数来自: P. L&#39; Ecuyer:1997年4月30日不同大小和良好晶格结构的线性同余发生器表。

答案 3 :(得分:38)

不,但这是一个简单的伪随机生成器,Multiply-with-carry的实现我改编自Wikipedia(之后已被删除):

var m_w = 123456789;
var m_z = 987654321;
var mask = 0xffffffff;

// Takes any integer
function seed(i) {
    m_w = (123456789 + i) & mask;
    m_z = (987654321 - i) & mask;
}

// Returns number between 0 (inclusive) and 1.0 (exclusive),
// just like Math.random().
function random()
{
    m_z = (36969 * (m_z & 65535) + (m_z >> 16)) & mask;
    m_w = (18000 * (m_w & 65535) + (m_w >> 16)) & mask;
    var result = ((m_z << 16) + (m_w & 65535)) >>> 0;
    result /= 4294967296;
    return result;
}

编辑:通过重置m_z来修复种子功能
EDIT2:修复了严重的实施缺陷

答案 4 :(得分:25)

AnttiSykäri的算法非常简短。当你调用Math.seed(s)时,我最初创建了一个替换Javascript的Math.random的变体,但后来Jason评论说返回函数会更好:

Math.seed = function(s) {
    return function() {
        s = Math.sin(s) * 10000; return s - Math.floor(s);
    };
};

// usage:
var random1 = Math.seed(42);
var random2 = Math.seed(random1());
Math.random = Math.seed(random2());

这为您提供了Javascript不具备的另一项功能:多个独立的随机生成器。如果您希望同时运行多个可重复的模拟,这一点尤为重要。

答案 5 :(得分:10)

请参阅Pierre L&#39; Ecuyer的工作,可追溯到20世纪80年代末和90年代初。还有其他人。如果您不是专家,自己创建一个(伪)随机数生成器是非常危险的,因为很可能结果不是统计随机的或者有一个小周期。皮埃尔(和其他人)已经将一些易于实现的好(伪)随机数生成器组合在一起。我使用他的一个LFSR发生器。

https://www.iro.umontreal.ca/~lecuyer/myftp/papers/handstat.pdf

菲尔·特洛伊

答案 6 :(得分:3)

结合以前的一些答案,这是您正在寻找的可种子随机函数:

Math.seed = function(s) {
    var mask = 0xffffffff;
    var m_w  = (123456789 + s) & mask;
    var m_z  = (987654321 - s) & mask;

    return function() {
      m_z = (36969 * (m_z & 65535) + (m_z >>> 16)) & mask;
      m_w = (18000 * (m_w & 65535) + (m_w >>> 16)) & mask;

      var result = ((m_z << 16) + (m_w & 65535)) >>> 0;
      result /= 4294967296;
      return result;
    }
}

var myRandomFunction = Math.seed(1234);
var randomNumber = myRandomFunction();

答案 7 :(得分:3)

编写自己的伪随机生成器非常简单。

Dave Scotese的建议很有用,但正如其他人所指出的那样,它的分布并不均匀。

但是,这不是因为sin的整数参数。这只是因为罪的范围,恰好是一个圆的一维投影。如果你采取圆的角度而不是它是均匀的。

因此,而不是罪(x)使用arg(exp(i * x))/(2 * PI)。

如果您不喜欢线性顺序,请将其与xor混合一点。实际因素并不重要。

要生成n个伪随机数,可以使用代码:

function psora(k, n) {
  var r = Math.PI * (k ^ n)
  return r - Math.floor(r)
}
n = 42; for(k = 0; k < n; k++) console.log(psora(k, n))

请注意,当需要真正的熵时,不能使用伪随机序列。

答案 8 :(得分:3)

如今,许多在Javascript中需要种子随机数生成器的人正在使用David Bau's seedrandom module

答案 9 :(得分:0)

Math.random不,但是ran library解决了这个问题。它几乎具有您可以想象的所有分布,并支持种子式随机数生成。示例:

ran.core.seed(0)
myDist = new ran.Dist.Uniform(0, 1)
samples = myDist.sample(1000)

答案 10 :(得分:0)

这是从 here 借用的 Jenkins 哈希的采用版本

export function createDeterministicRandom(): () => number {
  let seed = 0x2F6E2B1;
  return function() {
    // Robert Jenkins’ 32 bit integer hash function
    seed = ((seed + 0x7ED55D16) + (seed << 12))  & 0xFFFFFFFF;
    seed = ((seed ^ 0xC761C23C) ^ (seed >>> 19)) & 0xFFFFFFFF;
    seed = ((seed + 0x165667B1) + (seed << 5))   & 0xFFFFFFFF;
    seed = ((seed + 0xD3A2646C) ^ (seed << 9))   & 0xFFFFFFFF;
    seed = ((seed + 0xFD7046C5) + (seed << 3))   & 0xFFFFFFFF;
    seed = ((seed ^ 0xB55A4F09) ^ (seed >>> 16)) & 0xFFFFFFFF;
    return (seed & 0xFFFFFFF) / 0x10000000;
  };
}

你可以这样使用它:

const deterministicRandom = createDeterministicRandom()
deterministicRandom()
// => 0.9872818551957607

deterministicRandom()
// => 0.34880331158638

答案 11 :(得分:0)

这里的大多数答案都会产生有偏见的结果。所以这里有一个基于 seedrandom library from github 的测试函数:

!function(f,a,c){var s,l=256,p="random",d=c.pow(l,6),g=c.pow(2,52),y=2*g,h=l-1;function n(n,t,r){function e(){for(var n=u.g(6),t=d,r=0;n<g;)n=(n+r)*l,t*=l,r=u.g(1);for(;y<=n;)n/=2,t/=2,r>>>=1;return(n+r)/t}var o=[],i=j(function n(t,r){var e,o=[],i=typeof t;if(r&&"object"==i)for(e in t)try{o.push(n(t[e],r-1))}catch(n){}return o.length?o:"string"==i?t:t+"\0"}((t=1==t?{entropy:!0}:t||{}).entropy?[n,S(a)]:null==n?function(){try{var n;return s&&(n=s.randomBytes)?n=n(l):(n=new Uint8Array(l),(f.crypto||f.msCrypto).getRandomValues(n)),S(n)}catch(n){var t=f.navigator,r=t&&t.plugins;return[+new Date,f,r,f.screen,S(a)]}}():n,3),o),u=new m(o);return e.int32=function(){return 0|u.g(4)},e.quick=function(){return u.g(4)/4294967296},e.double=e,j(S(u.S),a),(t.pass||r||function(n,t,r,e){return e&&(e.S&&v(e,u),n.state=function(){return v(u,{})}),r?(c[p]=n,t):n})(e,i,"global"in t?t.global:this==c,t.state)}function m(n){var t,r=n.length,u=this,e=0,o=u.i=u.j=0,i=u.S=[];for(r||(n=[r++]);e<l;)i[e]=e++;for(e=0;e<l;e++)i[e]=i[o=h&o+n[e%r]+(t=i[e])],i[o]=t;(u.g=function(n){for(var t,r=0,e=u.i,o=u.j,i=u.S;n--;)t=i[e=h&e+1],r=r*l+i[h&(i[e]=i[o=h&o+t])+(i[o]=t)];return u.i=e,u.j=o,r})(l)}function v(n,t){return t.i=n.i,t.j=n.j,t.S=n.S.slice(),t}function j(n,t){for(var r,e=n+"",o=0;o<e.length;)t[h&o]=h&(r^=19*t[h&o])+e.charCodeAt(o++);return S(t)}function S(n){return String.fromCharCode.apply(0,n)}if(j(c.random(),a),"object"==typeof module&&module.exports){module.exports=n;try{s=require("crypto")}catch(n){}}else"function"==typeof define&&define.amd?define(function(){return n}):c["seed"+p]=n}("undefined"!=typeof self?self:this,[],Math);

function randIntWithSeed(seed, max=1) {
  /* returns a random number between [0,max] including zero and max
  seed can be either string or integer */
  return Math.round(new Math.seedrandom('seed' + seed)()) * max
}

测试这段代码的真正随机性:https://es6console.com/kkjkgur2/

答案 12 :(得分:-1)

我编写了一个返回种子随机数的函数,它使用Math.sin来获得一个长随机数,并使用种子从中选择数字。

使用:

seedRandom("k9]:2@", 15)

它将返回您的种子号码 第一个参数是任何字符串值;你的种子。 第二个参数是将返回多少位数。

     function seedRandom(inputSeed, lengthOfNumber){

           var output = "";
           var seed = inputSeed.toString();
           var newSeed = 0;
           var characterArray = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','y','x','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','U','R','S','T','U','V','W','X','Y','Z','!','@','#','$','%','^','&','*','(',')',' ','[','{',']','}','|',';',':',"'",',','<','.','>','/','?','`','~','-','_','=','+'];
           var longNum = "";
           var counter = 0;
           var accumulator = 0;

           for(var i = 0; i < seed.length; i++){
                var a = seed.length - (i+1);
                for(var x = 0; x < characterArray.length; x++){
                     var tempX = x.toString();
                     var lastDigit = tempX.charAt(tempX.length-1);
                     var xOutput = parseInt(lastDigit);
                     addToSeed(characterArray[x], xOutput, a, i); 
                }                  
           }

                function addToSeed(character, value, a, i){
                     if(seed.charAt(i) === character){newSeed = newSeed + value * Math.pow(10, a)}
                }
                newSeed = newSeed.toString();

                var copy = newSeed;
           for(var i=0; i<lengthOfNumber*9; i++){
                newSeed = newSeed + copy;
                var x = Math.sin(20982+(i)) * 10000;
                var y = Math.floor((x - Math.floor(x))*10);
                longNum = longNum + y.toString()
           }

           for(var i=0; i<lengthOfNumber; i++){
                output = output + longNum.charAt(accumulator);
                counter++;
                accumulator = accumulator + parseInt(newSeed.charAt(counter));
           }
           return(output)
      }

答案 13 :(得分:-1)

在 PHP 中,有函数 planes[2] = CompensationTermRed; 可以为特定种子生成固定的随机值。 但是,在 JS 中,没有这样的内置函数。

但是,我们可以编写简单而简短的函数。

步骤1:选择一些种子(固定号码)。
srand(seed)
数字应为正整数且大于 1,在步骤 2 中进一步说明。

步骤2:在Seed上执行Math.sin()函数,它会给那个数字的 sin 值。将此值存储在变量 x 中。

var seed = 100;

sin() 方法返回一个介于 -1 和 1 之间的小数值。
而且我们不需要负值,因此,第一步选择大于 1 的数字。 >

步骤3:返回值是一个介于 -1 和 1 之间的小数值。
因此,将此值与 10 相乘以使其大于 1。< /p>

var x; 
x = Math.sin(seed); // Will Return Fractional Value between -1 & 1 (ex. 0.4059..)

步骤4:将值乘以 10 以获得额外的数字

x = x * 10; // 10 for Single Digit Number

按数字要求相乘。

结果将以十进制表示。

步骤 5:通过 Math 的 Round (Math.round()) 方法删除小数点后的值。

x = x * 10; // Will Give value between 10 and 99 OR
x = x * 100; // Will Give value between 100 and 999

步骤6:通过Math.abs方法

将负值转化为正值(如果有)
x = Math.round(x); // This will give Integer Value.

解释结束。

最终代码

x = Math.abs(x); // Convert Negative Values into Positive(if any)

干净和优化的功能代码

var seed = 111; // Any Number greater than 1
var digit = 10 // 1 => single digit, 10 => 2 Digits, 100 => 3 Digits and so. (Multiple of 10) 

var x; // Initialize the Value to store the result
x = Math.sin(seed); // Perform Mathematical Sin Method on Seed.
x = x * 10; // Convert that number into integer
x = x * digit; // Number of Digits to be included
x = Math.round(x); // Remove Decimals
x = Math.abs(x); // Convert Negative Number into Positive

然后使用
调用这个函数 function random_seed(seed, digit = 1) { var x = Math.abs(Math.round(Math.sin(seed++) * 10 * digit)); return x; }
any_number 是必须的并且应该大于 1。
number_of_digits 是可选参数,如果没有传递任何参数,将返回 1 Digit .

random_seed(any_number, number_of_digits)

答案 14 :(得分:-3)

固定种子的简单方法:

function fixedrandom(p){
    const seed = 43758.5453123;
    return (Math.abs(Math.sin(p)) * seed)%1;
}

答案 15 :(得分:-5)

对于0到100之间的数字。

[10-04-2018 16:14:28.801] [ERROR][c.m.utils.CertificateUtils.verifySmartCardPresence(138)] - list() failed 
javax.smartcardio.CardException: list() failed
at sun.security.smartcardio.PCSCTerminals.list(Unknown Source) ~[na:1.8.0_161]
at javax.smartcardio.CardTerminals.list(Unknown Source) ~[na:1.8.0_161]
at com.mar.utils.CertificateUtils.verifySmartCardPresence(CertificateUtils.java:130) ~[mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at com.mar.ws.impl.SignWSImpl.signData(SignWSImpl.java:58) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_161]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_161]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_161]
at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_161]
at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:151) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:171) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:152) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:104) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:406) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:350) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:106) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:259) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.glassfish.jersey.internal.Errors.process(Errors.java:315) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.glassfish.jersey.internal.Errors.process(Errors.java:297) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.glassfish.jersey.internal.Errors.process(Errors.java:267) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:320) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:236) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1028) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:373) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:381) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:344) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:219) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:769) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:585) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:221) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1125) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1059) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.eclipse.jetty.server.Server.handle(Server.java:497) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:311) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:248) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:540) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:610) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:539) [mar-1.0-SNAPSHOT-jar-with-dependencies.jar:na]
at java.lang.Thread.run(Unknown Source) [na:1.8.0_161]
Caused by: sun.security.smartcardio.PCSCException: SCARD_E_SERVICE_STOPPED
at sun.security.smartcardio.PCSC.SCardListReaders(Native Method) ~[na:1.8.0_161]