小编Dav*_*ock的帖子

使用HttpRequest.execute()的异常:无效使用SingleClientConnManager:仍然分配了连接

我正在使用google-api-client-java 1.2.1-alpha来执行POST请求,并在执行()HttpRequest时获得以下stacktrace.

它在我捕获并忽略从先前的POST到同一URL的403错误后立即发生,并重新使用传输进行后续请求.(它在一个循环中插入多个条目到同一个ATOM提要).

在403之后,我应该做些什么来"清理"?

Exception in thread "main" java.lang.IllegalStateException: Invalid use of SingleClientConnManager: connection still allocated.
Make sure to release the connection before allocating another one.
    at org.apache.http.impl.conn.SingleClientConnManager.getConnection(SingleClientConnManager.java:199)
    at org.apache.http.impl.conn.SingleClientConnManager$1.getConnection(SingleClientConnManager.java:173)
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:390)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:576)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:554)
    at com.google.api.client.apache.ApacheHttpRequest.execute(ApacheHttpRequest.java:47)
    at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:207)
    at au.com.machaira.pss.gape.RedirectHandler.execute(RedirectHandler.java:38)
    at au.com.machaira.pss.gape.ss.model.records.TableEntry.executeModification(TableEntry.java:81)
Run Code Online (Sandbox Code Playgroud)

为什么我下面的代码会尝试获取连接?

java httpclient google-api-java-client

80
推荐指数
4
解决办法
6万
查看次数

当类暴露给线程池时,清理ThreadLocal资源真的是我的工作吗?

我使用ThreadLocal

在我的Java类中,我有时会ThreadLocal主要使用一种方法来避免不必要的对象创建:

@net.jcip.annotations.ThreadSafe
public class DateSensitiveThing {

    private final Date then;

    public DateSensitiveThing(Date then) {
        this.then = then;
    }

    private static final ThreadLocal<Calendar> threadCal = new ThreadLocal<Calendar>()   {
        @Override
        protected Calendar initialValue() {
            return new GregorianCalendar();
        }
    };

    public Date doCalc(int n) {
        Calendar c = threadCal.get();
        c.setTime(this.then):
        // use n to mutate c
        return c.getTime();
    }
}
Run Code Online (Sandbox Code Playgroud)

我这样做是出于正当的原因 - GregorianCalendar是那些光荣的有状态,可变,非线程安全的对象之一,它提供跨多个调用的服务,而不是表示值.此外,它被认为是"昂贵的"实例化(这是否真实不是这个问题的重点).(总的来说,我真的很佩服它:-))

Tomcat如何发牢骚

但是,如果我在任何聚集线程的环境中使用这样的类 - 并且我的应用程序无法控制这些线程的生命周期 - 那么就有可能发生内存泄漏.Servlet环境就是一个很好的例子.

事实上,当一个webapp停止时,Tomcat 7就像这样嘶嘶作响:

严重:Web应用程序[]创建了一个ThreadLocal,其键为[org.apache.xmlbeans.impl.store.CharUtil $ 1](值[org.apache.xmlbeans.impl.store.CharUtil$1@2aace7a7])和一个值类型为[java.lang.ref.SoftReference](值[java.lang.ref.SoftReference@3d9c9ad4]),但在Web应用程序停止时无法将其删除.线程将随着时间的推移而更新,以避免可能的内存泄漏.2012年12月13日下午12:54:30 org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks

(在特定情况下,甚至我的代码都没有这样做).

谁应该受到责备? …

java concurrency thread-local threadpool

42
推荐指数
2
解决办法
2万
查看次数

使用环回地址使用TCP/IP套接字进行IPC时,常见的网络堆栈是否会跳过较低级别PDU中的消息框架?

在某些环境(如Java)中,使用TCP/IP套接字使用"localhost"地址(IPv4中为127.0.0.1或IPv6中为:: 1)在同一主机上的进程之间传递消息是很自然的.(因为Java倾向于不在其API中公开其他IPC机制).

显然,通过管道传递消息或使用共享内存的IPC,这可能比IPC慢得多.

另一方面,如果TCP/IP网络堆栈意识到连接的两端都在环回接口上,那么它可能能够进行一些优化,这样效率可能与使用管道没有太大差别.

但是,常见的操作系统(Windows,Linux)是否在其TCP/IP堆栈中实现了这样的优化?

sockets tcp localhost processing-efficiency interprocess

13
推荐指数
2
解决办法
8421
查看次数

如果我在HttpServlet #init(ServletConfig)中分配实例字段,Servlet规范是否保证我可以在doGet()中读取它们?

Servlet规范规定容器将实例化我的单个实例java.servlet.HttpServlet,并从多个工作线程调用服务方法(doGet()/ doPost()).

根据正常的线程规则,不能保证init(ServeltConfig)"之前发生的" 实例级字段的分配由执行的其他线程从那些相同的字段读取doGet(),除非有人在某个时刻安排同步.

实际上,容器实际上可以进行某种外部同步,以确保init()"后续"线程可以看到完成的工作.

但是,Servlet规范是否明确保证我是线程安全的?我现在无法找到这样的保证,虽然我必须承认,自从Servlet 2.4以来,我还没有从端到端读取规范.

编辑

例如,由于一些回答者将事情搞砸了,我的问题是:Servlet规范是什么说下面的类是线程安全的?

@WebServlet (initParams = {@WebInitParam(name="b", value="true")})
public Decider extends HttpServlet {

    private boolean b = false;

    public void init(ServletConfig config) {
        this.b = Boolean.parseBoolean(config.getAttribute("b"));
    }

    public void doGet(HttpServletRequest req, HttpServletResponse res) {
        res.sendRedirect(b ? "/true" ? "/false");
    }

}
Run Code Online (Sandbox Code Playgroud)

当然,如果我这样做:

public static void main(String[] argv) {

      HttpServlet s = new Decider();

      Thread t1 = new Thread(new Runnable() {
        public …
Run Code Online (Sandbox Code Playgroud)

java servlets specifications thread-safety

5
推荐指数
1
解决办法
1556
查看次数

Java 12 中的“Windows 上的默认本机 GSS-API”是否可以通过使用执行 JVM 的用户的 Krb5 主体来支持 JAAS 的 SSO?

Vanilla Krb5LoginModule 正在运行,提示输入信用信息

到目前为止,在我的适度使用中JAAS -> JGSS -> Kerberos -> Windows,我设置了一个Krb5LoginModuleWhen I do:

Subject.doAs(
    new LoginContext(...)).login(),  // subject
    new MyPrivilegedAction()         // action
)
Run Code Online (Sandbox Code Playgroud)

...系统提示我输入凭据,并且操作成功。

使用 TGT Session Key hack,可以避免提示输入信用信息

如果我也添加useTicketCache=true到登录模块,并且如果我忍受设置的安全隐患HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Parameters\AllowTgtSessionKey=1并且不使用 Windows 10 Credential Guard,那么操作就会成功,而无需提示输入凭据。

Java 12 为我们提供了默认的本机 GSS-API 库,即使在 Windows 上也是如此

Java 11.0.10引入了在 Windows 上使用本机 GSS-API 实现的可能性,但没有提供默认实现。Java 12添加了 GSS-API 的本机实现,可桥接到 Windows SSPI。这避免了冒险的需要AllowTGTSessionKey

使用本机 GSS-API 也可以,提示输入信用信息

在 Windows 上的 Java 15.0.2(Oracle 和 OpenJDK)上,尽管文档仍然(现在错误地)声称“Windows …

java windows kerberos jaas jgss

5
推荐指数
0
解决办法
938
查看次数

jOOQ 与 Kotlin 协程配合得很好吗?

Kotlin 协程和“挂起函数”使程序员可以轻松等待 I/O 结果,而无需停止线程(在 I/O 完成之前,线程会被赋予其他工作要做)。

jOOQ是一个 Java 优先产品,用于以类型安全的方式编写和执行 SQL,但它本身并不显式使用 Kotlin 协程。

是否可以从 Kotlin 协同例程作用域调用 jOOQ 以获得易于编写和线程即使在 IO 期间也能高效运行的优点?

suspend fun myQuery() {
  return dsl.select()
  // .etc()
  .fetch()  // <- could this be a 'suspend' call?
}
Run Code Online (Sandbox Code Playgroud)

nonblocking jooq kotlin-coroutines

4
推荐指数
1
解决办法
2248
查看次数

可以使用按位运算符将4个无尾符号整数的小端序列字节分配给Java原语吗?

我想读取4个字节,它是无符号32位整数的小端编码,并将值赋给Java int

(是的,实际上我会使用'long',但在这种情况下我知道'无符号值永远不会那么大,它会以二进制补码表示法溢出一个带符号的int,并且它适合我的插图使用一个int ).

有问题的4个字节编码值'216'little-endian样式:

0xD8000000
Run Code Online (Sandbox Code Playgroud)

基本上我只需要将以下位模式填充到Java int中:

0x000000D8
Run Code Online (Sandbox Code Playgroud)

下面的简单代码应该这样做......对于前三个'0x00'字节,它成功:

byte b1 = din.readByte();
byte b2 = din.readByte();
byte b3 = din.readByte();
byte b4 = din.readByte();
int s = 0;
s = s | b4;
s = (s << 8);
s = s | b3;
s = (s << 8);
s = s | b2;
s = (s << 8);
s = s | b1;
return s;
Run Code Online (Sandbox Code Playgroud)

然而,它搞砸了:

s = s | b1;
Run Code Online (Sandbox Code Playgroud)

...因为b1的位是1101 1000,这是二进制补码表示法中的负数(-40),因为最高有效位是1.当Java在按位或运算符进行求值之前将b1扩展为int. ,-40编码为0xFFFFFFD8,这使我们天真的假设,即加宽int的前3个字节将为0.

所以我的策略搁浅了.但我该怎么做呢?甚至可以使用原始运算符解决这个问题(请给出解决方案),还是我们必须求助于类库?(我不会在我的正常编码中直接使用位和字节,所以我缺乏成语似乎应该是'每天'代码).

对于类库方法,以下片段得到了正确的结果:

ByteBuffer b …
Run Code Online (Sandbox Code Playgroud)

java endianness bitwise-operators numeric-conversion

1
推荐指数
1
解决办法
1520
查看次数