我正在使用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类中,我有时会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是那些光荣的有状态,可变,非线程安全的对象之一,它提供跨多个调用的服务,而不是表示值.此外,它被认为是"昂贵的"实例化(这是否真实不是这个问题的重点).(总的来说,我真的很佩服它:-))
但是,如果我在任何聚集线程的环境中使用这样的类 - 并且我的应用程序无法控制这些线程的生命周期 - 那么就有可能发生内存泄漏.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)中,使用TCP/IP套接字使用"localhost"地址(IPv4中为127.0.0.1或IPv6中为:: 1)在同一主机上的进程之间传递消息是很自然的.(因为Java倾向于不在其API中公开其他IPC机制).
显然,通过管道传递消息或使用共享内存的IPC,这可能比IPC慢得多.
另一方面,如果TCP/IP网络堆栈意识到连接的两端都在环回接口上,那么它可能能够进行一些优化,这样效率可能与使用管道没有太大差别.
但是,常见的操作系统(Windows,Linux)是否在其TCP/IP堆栈中实现了这样的优化?
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) 到目前为止,在我的适度使用中JAAS -> JGSS -> Kerberos -> Windows,我设置了一个Krb5LoginModuleWhen I do:
Subject.doAs(
new LoginContext(...)).login(), // subject
new MyPrivilegedAction() // action
)
Run Code Online (Sandbox Code Playgroud)
...系统提示我输入凭据,并且操作成功。
如果我也添加useTicketCache=true到登录模块,并且如果我忍受设置的安全隐患HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Parameters\AllowTgtSessionKey=1并且不使用 Windows 10 Credential Guard,那么操作就会成功,而无需提示输入凭据。
Java 11.0.10引入了在 Windows 上使用本机 GSS-API 实现的可能性,但没有提供默认实现。Java 12添加了 GSS-API 的本机实现,可桥接到 Windows SSPI。这避免了冒险的需要AllowTGTSessionKey。
在 Windows 上的 Java 15.0.2(Oracle 和 OpenJDK)上,尽管文档仍然(现在错误地)声称“Windows …
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) 我想读取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 ×5
concurrency ×1
endianness ×1
httpclient ×1
interprocess ×1
jaas ×1
jgss ×1
jooq ×1
kerberos ×1
localhost ×1
nonblocking ×1
servlets ×1
sockets ×1
tcp ×1
thread-local ×1
threadpool ×1
windows ×1